从基本抽象类构造子类
我想在抽象类中定义一个构造函数来创建具体的子类。
abstract class A {
type Impl <: A
def construct() : Impl = {
val res = new Impl() //compile error: class type required but A.this.Impl found
// do more initialization with res
}
}
class B extends A {type Impl = B}
class C extends A {type Impl = C}
//...
val b = new B
b.construct() // this should create a new instance of B
这里有什么问题吗?这有可能实现吗? 编辑:澄清:我想抽象构造方法。我不想从子类或伴随对象中单独调用 new B
和 new C
。
I want to define a constructor in an abstract class that will create concrete subclasses.
abstract class A {
type Impl <: A
def construct() : Impl = {
val res = new Impl() //compile error: class type required but A.this.Impl found
// do more initialization with res
}
}
class B extends A {type Impl = B}
class C extends A {type Impl = C}
//...
val b = new B
b.construct() // this should create a new instance of B
What is wrong here? Is this even possible to implement?
EDIT: Clarification: I want to abstract over the construct method. I do not want to call separately new B
and new C
from either subclasses or companion objects.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果要创建新实例,则需要显式调用构造函数。
Scala 在运行时擦除类型,因此无法知道创建类时 Impl 的含义。
You need to explicitly invoke a constructor if you want create a new instance.
Scala erases type at runtime so there is no way to know what Impl meant when the class was created.
您可以将构造函数放在伴生对象中,而不是放在抽象类中。像这样:
现在,您可以通过调用
A(42)
或A("foobar")
创建A
的实例,例如。当然,字符串和整数参数只是示例。如果所有构造函数的参数具有相同的类型,则此重载将不起作用。在这种情况下,您可以轻松创建不同的方法并将它们称为apply
以外的名称。You would put the constructor in the companion object, not in the abstract class. Like this:
Now, you could create an instance of
A
by callingA(42)
, orA("foobar")
, for example. The string and integer parameters are only examples, of course. If the parameters for all the constructors have the same types, this overloading will not work. In that case, you can easily create different methods and call them something other thanapply
.您可以使用反射来创建新实例。像这样的事情会起作用,但在我看来不值得这么麻烦。一方面,您只能检查运行时是否存在合适的构造函数。
You can use reflection to create a new instance. Something like this would work but in my opinion is not worth the trouble. For one thing you would only be able to check if a suitable constructor existed at runtime.
看来这是不可能的。根据 Scala 书(作者:Oderski、Spoon、Venners),您无法创建抽象类型的实例。请参阅:抽象类型章节,货币案例研究。稍后可能会通过“虚拟类”来支持这一点。
Looks like this is not possible. According to the Scala book (by Oderski, Spoon, Venners) you cannot create an instance of an abstract type. See: Abstract Types chapter, Currencies case study. This may be supported later with "virtual classes".
我建议采用以下模式:
您现在拥有的所有冗余恰好是每个子类一行。我认为这是一个很小的代价:a)一个可行的解决方案,b)不使用反射(这基本上破坏了静态类型系统为您提供的所有保证)。
我仍然很好奇为什么你需要在
A
中构建construct
。闻起来有鱼腥味。I propose the following pattern:
All reduandancy you have now is precisely one line per subclass. I consider this a small price to pay for a) a working solution that b) does not use reflection (which breaks essentially all guarantees a static type system offers you).
I am still curious why you would need
construct
insideA
. Smells fishy.按照我在
Monkey
回复中留下的评论。解决此问题的一种方法是使用 Curiously Recurring Template Pattern (CRTP) 和self types:也许有更好的解决方案,但这是迄今为止我发现的。
Following my comment left at
Monkey
response. One way how to solve this is to use the Curiously Recurring Template Pattern (CRTP) together with a self types:Perhaps there is a better solution, but this is so far what I found.