1

我有一个奇怪的问题,可能是因为我的课程结构有点复杂,但无论如何:

所以首先我有 2 个抽象类:TestAbstract1 和 TestAbstract2。

  • TestAbstract2采用扩展 TestAbstract1 的类型
  • TestAbstract1声明了一个名为valTest的类型 TestAbstract2[TestAbstract1] 的 val,它必须在子类中实现

代码 :

abstract class TestAbstract1 {
    val valTest: TestAbstract2[TestAbstract1]

    def meth1(): List[TestAbstract1] = {
        valTest.meth2()
    }
}

abstract class TestAbstract2[T <: TestAbstract1] {
    def meth2(): List[T] = {
        List()
    }
}

然后我有一个扩展TestAbstract2的对象TestObject2,以及一个扩展TestAbstract1的基本类Test2,并且必须实现valTest

class Test2 extends TestAbstract1 {
    val valTest: TestAbstract2[Test2] = TestObject2
}

object TestObject2 extends TestAbstract2[Test2] { }

问题在这里:当我编译时,它告诉我:

[错误] 覆盖类型为 models.test.TestAbstract2[models.test.TestAbstract1] 的类 TestAbstract1 中的值 valTest;

[错误] 值 valTest 的类型不兼容

[错误] val valTest:TestAbstract2[Test2] = TestObject2

我不知道我做错了什么,因为如果我考虑多态规则,应该没问题...

你有什么主意吗 ?或者甚至是做我想做的更好的方法?

谢谢 !

4

1 回答 1

5

在您的示例中,TestAbstract2不是协变的。这意味着即使我们有

Test2 <: TestAbstract1

情况并非如此:

TestAbstract2[Test2] <: TestAbstract2[TestAbstract1]

如果这对您没有意义,请查看此处。

在您的示例中,valTest如 in 声明的Test2is 类型TestAbstract2[Test2]但预期为TestAbstract2[TestAbstract1],因此错误。

您有以下选择:

  1. 声明TestAbstract2为协变:

    class TestAbstract2[+T <: TestAbstract1]
    
  2. valTest使用通配符类型声明:

    val valTest: TestAbstract2[_ <: TestAbstract1]
    
  3. 参数TestAbstract1化内部的类型TestAbstract2

    class TestAbstract1[T <: TestAbstract1[T]] {
      val valTest: TestAbstract2[T]
      // ...
    }
    

    更改Test2为:

    class Test2 extends TestAbstract1[Test2]
    

请注意,在第三个示例中使用 F 有界多态性(T由 中自身的函数限制TestAbstract1)的选择在这里有些随意。为了示例,我只需要输入一些类型,并且在您的示例中它可以工作(在查看 的定义时Test2)。这三个版本中的哪一个最适合您,取决于您希望如何使用这些类。

如果这对您来说还不够,请在您的问题中提供更多详细信息,我们很乐意提供帮助。

于 2013-06-29T00:50:46.433 回答