本文介绍了Scala抽象类型在对象中的类中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我这样做:

object Parent {
    class Inner extends Testable { type Self <: Inner }
    def inner = new Inner()
}

object Child {
    class Inner extends Parent.Inner { type Self <: Inner }
    def inner = new Inner()
}

trait Testable {
    type Self
    def test[T <: Self] = {}
}

object Main {
    // this works
    val p: Parent.Inner = Child.inner
    // this doesn't
    val h = Parent.inner
    h.test[Child.Inner]
}

I得到此错误:

error: type arguments [Child.Inner] do not conform to method test's type parameter bounds [T <: Main.h.Self]
    h.test[Child.Inner]

为什么当我的自我类型是Parent.Inner和Child.Inner<:Parent.Inner?

Why does this error when I my Self type is Parent.Inner and Child.Inner <: Parent.Inner?

这个错误我更改键入Self< ;: Inner 键入Self = Inner 然后覆盖类型Self = Inner ,我收到此错误:

And if I change type Self <: Inner to type Self = Inner and then override type Self = Inner, I get this error:

overriding type Self in class Inner, which equals Parent.Inner;
 type Self has incompatible type
    class Inner extends Parent.Inner { override type Self = Inner }


推荐答案

这是路径相关类型的问题。

test 对象的方法 h 如你所假设的那样,并不期望的子类型Parent.Inner 。它期望一个 h.Self 的子类型,这是一种稍微不同的类型。即使 Child.Inner Parent.Inner 的子类型,它也不是 h.Self 这就是编译器抱怨的原因。

The test method of object h does not expect, as you would assume, a subtype of Parent.Inner. It expects a subtype of h.Self which is a slightly different type. Even though Child.Inner is a subtype of Parent.Inner, it is not a subtype of h.Self and that's why the compiler complains.

类型成员的问题是它们路径依赖 - 它们绑定到它们的封闭实例,并且scalac不允许您传递一个实例的类型成员,其中需要另一个实例的类型成员。 Child.Inner 根本没有绑定到任何实例,也会被拒绝。

The problem with type members is that they are path dependent - they're bound to their enclosing instance and scalac will not allow you to pass type member of one instance where type member of another instance is expected. Child.Inner is not bound to any instance at all and will also be rejected.

为什么需要这样做?看看这个非常相似的代码:

Why is this needed? Look at this very similar code:

object Main {
  class C extends Child.Inner { type Self = C }

  val h: Parent.Inner = new C
  h.test[Child.Inner]
}

在查看类型时,此代码与您的代码完全相同(特别是 h 的类型正是相同)。但是这段代码显然不正确,因为 h.Self 实际上是 C Child.Inner 不是 C 的子类型。这就是scalac正确拒绝它的原因。

When looking at types, this code is exactly the same as yours (in particular, the type of h is exactly the same). But this code is clearly incorrect, because h.Self is actually C and Child.Inner is not a subtype of C. That's why scalac correctly rejects it.

您可能希望在您的代码段scalac中记住 h 的类型是完全 Parent.Inner ,但不幸的是它没有保留这些信息。它只知道 h Parent.Inner 的某个子类型。

You would expect that in your snippet scalac should remember that the type of h is exactly Parent.Inner, but unfortunately it doesn't keep that information. It only knows that h is some subtype of Parent.Inner.

这篇关于Scala抽象类型在对象中的类中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 05:04