简体   繁体   English

如何使用泛型从Scala方法返回

[英]How to return from Scala method with generics

I have two trait 我有两个特点

trait TResponseData extends Serializable {} //all response data
trait TRequestData extends Serializable {} //all request

Now I have Response class, which contains data and request 现在我有了Response类,其中包含数据和请求

case class Response[A <: TResponseData, B <: TRequestData](data: A, request: B = null){}

While instance of case class Response must have data, request is not mandatory. 尽管案例类Response的实例必须具有数据,但请求不是必需的。 So I declared its default to null in case class constructor. 因此,在case类构造函数中,我将其默认声明为null。 From Scala console, I am able to create its instance like 从Scala控制台,我可以创建其实例,例如

Response(null, null)
Response(null)

To generate instance of Response , I have created helper method: 为了生成Response的实例,我创建了辅助方法:

def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] = {
    if (passRequestInResponse) 
        return Response(data, request)
    return Response(data, null)
}

Based on boolean passRequestInResponse , I am setting request in Response. 基于boolean passRequestInResponse ,我在响应中设置请求。 On compiling same, I am getting follow error: 在进行相同的编译时,出现以下错误:

error: type mismatch;
 found   : Null(null)
 required: B
           return Response(data, null)

How can I achieve same (making request optional in generateResponse method) 我如何实现相同(使请求在generateResponse方法中为可选)

You can either modify the generateResponse() return type... 您可以修改generateResponse()返回类型...

def generateResponse[A <: TResponseData, B <: TRequestData] (data: A
                                                            ,request: B
                                                            ,passRequestInResponse: Boolean
                                                            ): Response[A, _] = 
  if (passRequestInResponse) Response(data, request)
  else                       Response(data, null)

... or you can cast the null to the required type. ...,也可以将null转换为所需的类型。

def generateResponse[A <: TResponseData, B <: TRequestData] (data: A
                                                            ,request: B
                                                            ,passRequestInResponse: Boolean
                                                            ): Response[A, B] = 
  if (passRequestInResponse) Response(data, request)
  else                       Response(data, null.asInstanceOf[B])

(But don't use return . It's not idiomatic Scala.) (但不要使用return 。这不是惯用的Scala。)

In general, I don't really see why you need generateResponse() at all. 总的来说,我根本看不出为什么根本需要generateResponse() The Response constructor will still either have a B or it won't, so it should be an Option[B] that defaults to None . Response构造函数仍将带有B或没有B ,因此为默认为NoneOption[B] (Idiomatic Scala avoids null .) (惯用的Scala避免使用null 。)

Using null is a bad idea (as is return ) so it is better to use Option : 使用null是一个坏主意(就像return ),因此最好使用Option

trait TResponseData extends Serializable //all response data
trait TRequestData extends Serializable //all request

case class Response[A <: TResponseData, B <: TRequestData](data: A, request: Option[B]=None)

def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] =
  if (passRequestInResponse) {
    Response(data, Some(request))
  } else {
    Response(data)
  }

You can also do some Option magic like this: 您也可以像下面这样做一些Option Magic:

def generateResponse[A <: TResponseData, B <: TRequestData] (data: A, request: B, passRequestInResponse: Boolean): Response[A, B] =
  Response(
    data,
    Some(request).filter(_ => passRequestInResponse)
  )

The advantage of this formulation is that it will work if request is null , and will treat this case as if passRequestInResponse was false 这种表述的优点在于,如果requestnull ,它将起作用,并且将passRequestInResponsefalse

Update 更新资料

As noted by @jwvh it is not clear that the generateResponse function is useful because you can just call Response(data, Some(request)) or Response(data) as needed. 如@jwvh所指出的,不清楚generateResponse函数是否有用,因为您可以根据需要调用Response(data, Some(request))Response(data) If you don't like that Some in the first version, then create a class object with a custom apply method: 如果您不喜欢第一个版本中的Some ,请使用自定义apply方法创建一个类对象:

object Response {
  def apply[A <: TResponseData, B <: TRequestData](data: A, request: B): Response[A, B]
    = Response(data, Option(request))
}

Then you can just use Response(data, request) . 然后,您可以只使用Response(data, request) This will work correctly if request is null . 如果requestnull这将正常工作。

The reason for the error is that all types in Scala have a bottom type of Nothing. 该错误的原因是,Scala中的所有类型都具有Nothing的底部类型。 Nothing cannot accept the "null" value and therefore the type definition is problematic as B can be Nothing. 没有什么不能接受“空”值,因此类型定义存在问题,因为B可以为Nothing。

To solve this you can add a lower bound: 为了解决这个问题,您可以添加一个下限:

 def generateResponse[A <: TResponseData, B >: Null <: TRequestData ] (data: A, request: B,
                                                           passRequestInResponse: Boolean): Response[A, B] = {

this will mean that Nothing is an illegal type for B as the minimum allowed in Null. 这将意味着B没有任何非法类型,因为Null是允许的最小值。

The use of Option[B] is probably a better idea and should be used in this case in term of good design, however, in more generic cases there are situations where lower bound would be better. 使用Option [B]可能是一个更好的主意,应该在这种情况下使用良好的设计,但是,在更通用的情况下,存在下限会更好的情况。

PS you shouldn't be using return. PS,您不应该使用return。 As you can see in other answers you can do: 如您在其他答案中所见,您可以执行以下操作:

if (passRequestInResponse) {
  Response(data, Some(request))
} else {
  Response(data)
}

as this will give the value. 因为这会带来价值。 Return is actually a control flow breaking (it is implemented with an exception) and can have unintended consequences. 返回实际上是控制流中断(它是通过异常实现的),并且可能产生意想不到的后果。 See for example https://blog.knoldus.com/scala-best-practices-say-no-to-return/ 参见例如https://blog.knoldus.com/scala-best-practices-say-no-to-return/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM