【问题标题】:Java inheritance; passing a subclass to an abstract method of a superclassJava继承;将子类传递给超类的抽象方法
【发布时间】:2014-05-28 16:29:17
【问题描述】:

抱歉标题,找不到更清晰的内容。 我有以下结构:

public interface Vehicle {...}
public class Car implements Vehicle {...}

然后:

public abstract class Fixer {
...
   abstract void fix(Vehicle vehicle);
...
}

并且想拥有:

public class CarFixer extends Fixer {
    void fix(Car car) {...}
}

但这不起作用。 Eclipse 说:The type CarFixer must implement the inherited abstract method Fixer.fix(Vehicle)。知道如何解决这个问题吗?

【问题讨论】:

  • 那是因为 Eclipse 是对的。重载不是覆盖。考虑一个通用的Fixer 类,也许?

标签: java inheritance interface abstract


【解决方案1】:

你可以使用泛型来解决这个问题:

public abstract class Fixer<T extends Vehicle> {
    abstract void fix(T vehicle);
}

public class CarFixer extends Fixer<Car> {
    void fix(Car car) {...}
}

您的原始版本的问题是fix 方法允许任何类型的车辆,但您的实现类只允许汽车。考虑这段代码:

Fixer fixer = new CarFixer();
fixer.fix(new Bike()); // <-- boom, `ClassCastException`, Bike is a vehicle but not a car

【讨论】:

    【解决方案2】:

    你见过generics的简陋家。

    泛型提供了一种'通配符'类型,其中类或方法可以指定'我们并不真正关心它是什么类型,我们只需要-a-类型'。

    泛型允许 super 类在 child 类中强制执行特定类型,而不是允许 any 类扩展某个特定类型类。

    这意味着您最终将强制执行一个新的允许的最高超类作为参数(即Vehicle 不再是您可以传递给fix() 的最基本的允许类型;它是现在无论子类说什么,只要该任意类型扩展 Vehicle)。

    泛型的常见位置是container classes(即List、Map 和Set),其中容器并不真正关心它跟踪的类型,而是专注于实际跟踪和管理这些实例.

    泛型由一个或多个类型占位符组成(在 Java 中,E 和 T 是常用的,但名称并不重要;它们通常遵循正常的类型命名约定)用于代替特定类或超类。


    在您的代码中,您希望子类在给定其确切相关类型的情况下实现方法(即 CarFixer 将采用 Cars,JetpackFixer 将采用 Jetpacks)但您希望强制这些类型扩展Vehicle。

    为了强制执行此操作,您必须准确地告诉 Fixer 类您的子类想要什么。

    public abstract class Fixer <E extends Vehicle>
    {
        abstract void fix(E vehicle);
    }
    

    然后您的子类扩展 Fixer,用它想要的类型填充 E。

    public class CarFixer extends Fixer<Car>
    {
        @Override
        void fix(Car vehicle)
        {
             // ...
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-12-09
      • 2010-09-29
      • 1970-01-01
      • 1970-01-01
      • 2012-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多