[英]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
,因此应为默认为None
的Option[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
这种表述的优点在于,如果
request
为null
,它将起作用,并且将passRequestInResponse
为false
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
. 如果
request
为null
这将正常工作。
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.