问题描述
我希望能够使用 this.type 来定义一个方法来创建不可变 case 类的新实例.像这样:
I'd like to be able to use this.type to define a method that makes new instances of an immutable case class. Something like this:
trait Expression
{
def left : Expression
def right : Expression
def new_with_changes(l : Expression, r : Expression) : this.type
}
case class Derived(left : Expression, right : Expression)
{
def new_with_changes(l : Expression, r : Expression) : this.type =
{
new Derived(left, right)
}
}
不幸的是,编译器抱怨
test.scala:13: error: type mismatch;
found : Derived
required: Derived.this.type
new Derived(left, right)
^
one error found
为什么新的 case 类与 this.type 不匹配?
How come the new case class doesn't match this.type?
如果我在 Base.new_with_changes 中将 this.type 更改为 Base 并在 Derived.new_with_changes 中将 Derived 更改为有效,但似乎忽略了 this.type 的优点.
If I change this.type to Base in Base.new_with_changes and Derived in Derived.new_with_changes that works, but it seems it's missing out on the nicety of this.type.
问题的真正意图是为什么在 Scala 中没有等效的方式来声明 down 的调用者执行向下转换,与 this.type 的方式非常相似,但适用于一般类型.我认为这并不容易,但会很好.
The real intent of the question is why not have an equivalent way in Scala to declare that the caller of the down perform the downcast, much in the same way that this.type does, but for general types. I don't think it would be easy, but it would be nice.
推荐答案
[注意:我不建议你这样做.] 你有很大的机会完成你想要的.对 this.type 的强制转换是一个谎言,但 JVM 不知道这一点,也不能抛出异常,因为单例类型是一个 Scala 概念.
[Note: I am not recommending that you do this.] There's a fair chance you can accomplish what you want. The cast to this.type is a lie, but the JVM doesn't know that and can't throw an exception because the singleton type is a scala concept.
现在如果你真的在任何地方使用 this.type 的单例属性,这会给你带来麻烦.但是,如果您想要做的只是获得协变返回类型而无需输入它们的所有麻烦,那么只有到处都是巨大的丑陋演员的小缺点:
Now if you're actually using the singleton property of this.type anywhere, this will get you in trouble in a hurry. But if all you want to do is get covariant return types without all the trouble of typing them, with only the small downside of the huge ugly cast all over the place:
trait Expression
{
def left : Expression
def right : Expression
def new_with_changes(l : Expression, r : Expression) : this.type
}
case class Derived1(left : Expression, right : Expression) extends Expression {
def new_with_changes(l : Expression, r : Expression) =
Derived1(left, right).asInstanceOf[this.type]
def foo() = "Derived1"
}
case class Derived2(left : Expression, right : Expression) extends Expression {
def new_with_changes(l : Expression, r : Expression) =
Derived2(left, right).asInstanceOf[this.type]
def bar() = "Derived2"
}
在行动中:
scala> Derived1(Derived1(null,null), null)
res0: Derived1 = Derived1(Derived1(null,null),null)
scala> res0.new_with_changes(res0, null).bar
<console>:6: error: value bar is not a member of Derived1
res0.new_with_changes(res0, null).bar
^
scala> res0.new_with_changes(res0, null).foo
res2: java.lang.String = Derived1
scala> Derived2(Derived2(null, null), null)
res3: Derived2 = Derived2(Derived2(null,null),null)
scala> res3.new_with_changes(null, res3).foo
<console>:6: error: value foo is not a member of Derived2
res3.new_with_changes(null, res3).foo
^
scala> res3.new_with_changes(null, res3).bar
res6: java.lang.String = Derived2
这篇关于为什么 this.type 不能用于新实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!