Sorry for the confusing title.
I am attempting to write some Request
and Response
classes for validation and parsing purposes. I'd like to have some guarantees of the type at compile-time, but still have runtime polymorphism. I have the following base classes:
abstract class Response()
abstract class Request() {
type ResponseType = Response
def ResponseClass: Class[_ <: ResponseType] = classOf[ResponseType]
}
so if I have an instance of type _ <: Request
, I can parse, for instance a JSON response, with the correct type: Json.parse(responseString).as[request.ResponseType]
.
I find that when I extend these classes, I am unable to override
the ResponseType
:
case class AddedFooResponse() extends Response
case class AddFooRequest() extends Request {
override type ResponseType = AddedFooResponse
}
error: overriding type
ResponseType
in classRequest
, which equalsthis.Response
; typeResponseType
has incompatible typeoverride type ResponseType = AddedFooResponse
I am unsure why the types are incompatible. My current workaround is a bit clumsy, which is to bound the type in the base classes:
abstract class Response()
abstract class Request() {
type ResponseType <: Response
// cannot initialize because no concrete class
def ResponseClass: Class[_ <: ResponseType]
}
and simply override both the ResponseType
and the ResponseClass
:
case class AddedFooResponse() extends Response
case class AddFooRequest() extends Request {
override type ResponseType = AddedFooResponse
override def ResponseClass = classOf[ResponseType]
}
This requires a lot of (seemingly) unnecessary boilerplate for overriding the ResponseClass
.
What am I doing incorrectly?
I think you could get away by not setting a default value for this type:
abstract class RequestBase() {
type ResponseType
def ResponseClass: Class[_ <: ResponseType] = classOf[ResponseType]
}
type Request = RequestBase { type ResponseType = Response }
case class AddFooRequest() extends Request {
override type ResponseType = AddedFooResponse
}
I found that I can forego completely the ResponseClass
by simply setting the ResponseType
and matching based on the instance returned by whatever uses that ResponseType
, lest it'll parse incorrectly and throw an exception.
abstract class Response
abstract class Request[+ResponseType <: Response]
case class FooResponse() extends Response {
def greet = println("woo hoo!")
}
case class FooRequest() extends Request[FooResponse] {
type ResponseType = FooResponse
}
val req: FooRequest = new FooRequest()
// Erase the type by making it an Object.
val resp: Object = new FooResponse()
resp.asInstanceOf[req.ResponseType] match {
case fooResp: FooResponse => fooResp.greet
case _ => println("This isn't good...")
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.