【问题标题】:scala inheritance and lower bound issuescala继承和下限问题
【发布时间】:2011-11-05 21:13:26
【问题描述】:

我在 scala 中遇到了一些继承和下限问题;我将尝试用一个例子来解释它: 我有一个类 Person,其签名如下:

def doSomething[P<%Person](persons :List[P]) {
}

我还创建了一个子类Worker,他的方法doSomething看起来是这样的:

override def doSomething(persons: List[Worker]) {
}

但是这会引发一个错误,指出 Worker.doSomething() 没有覆盖任何东西?

【问题讨论】:

    标签: scala lower-bound


    【解决方案1】:

    一个特定的方法不能覆盖一个泛型方法(尽管一个特定的类可以扩展一个泛型类),因为泛型方法说只要你将它传递给它any person 的子类,它就可以工作。具体方法不会取any子类;只需Worker

    【讨论】:

    • 感谢您的回答,但是在 Worker.doSomething() 方法中,我想访问 Worker 类的属性(不在通用 Person 类中)。有没有办法访问这些属性(不强制转换)?
    • @user485659 - 你能描述一下你想要做什么吗?正如我的回答所强调的那样,覆盖类在逻辑上是不正确的;转换也将是(逻辑上,如果不是实际上)不正确的,因为转换可能会失败(即,该方法不能保证仅使用 List[Worker] 作为与 Persons 一起使用的通用代码中的参数调用)。
    • @user485659 如果您还有其他问题,请在另一个问题中提出。但是,简而言之,你永远不应该问对象的东西。相反,您应该告诉它要做什么,在这种情况下,它会处理机制本身。但是,您可以使用模式匹配来避免遵循良好做法。
    【解决方案2】:

    您不能以这种方式继承。它违反了Liskov Substitution Principle。我会说明为什么会这样。假设你可以编译这些类:

    class Person {
        def doSomething[P<%Person](persons :List[P]) {
        }
    }
    
    class Worker extends Person {
        override def doSomething(persons: List[Worker]) {
        }
    }
    

    现在,这个简单的程序会失败:

    val p1: Person = new Worker
    val p2: Person = new Person
    p1.doSomething(List(p2))
    

    由于p2 不是Worker,因此该调用无效。但是,由于p1Person,因此该调用是有效的!这种矛盾是您提出的覆盖的结果。

    但比这更糟糕!这也不起作用:

    p1.doSomething[Worker](List(p1))
    

    现在,即使它传递了一个工人列表,正如p1 所期望的那样,它还是失败了,因为Worker 中的doSomething 不需要类型参数。但是,Person 的方法doSomething 声明应该传递一个类型参数!同样,矛盾是您提出的覆盖的结果。

    请记住,继承是一种 is-a 类型的关系。如果WorkerPerson,那么它应该行动Person 在所有方面都希望Person 行动。如果这不是您想要创建的那种关系,请不要使用继承。

    【讨论】:

      猜你喜欢
      • 2021-07-31
      • 2013-06-26
      • 1970-01-01
      • 1970-01-01
      • 2020-11-11
      • 2023-03-25
      • 1970-01-01
      • 2011-02-19
      相关资源
      最近更新 更多