【问题标题】:Making an overriden method's super refer to the superclasss super制作一个被覆盖的方法是super 引用超类super
【发布时间】:2016-05-29 20:59:11
【问题描述】:

我知道这个标题可能听起来有点奇怪,但这正是我愿意做的。简单解释: Class Aclass B 的子类,class B 也是class C 的子类。

现在,所有这些类都包含方法m()。在我的A 类中,我唯一可以访问的类,因为其他类仅在运行时可用,所以我覆盖了B 类的m() 方法。 但是,B 类的 m() 方法包含对其自身超类(即C)的m() 方法的调用,尽管我对其进行了一些修改,但我最终也不得不调用那个方法。

我搜索了一段时间,听说在类似情况下这是不可能的,因为它会“破坏封装”,我真的明白为什么。但是,就我而言,我是在一个被覆盖的方法中完成这一切的,所以有什么方法可以让我真正做到这一点,让它以这种方式工作吗?谢谢!

编辑: 啊,我想我没有很好地解释安静。我只是在我的 C 类中覆盖 B 类的方法。从那里,在我的 C 类方法中,我需要调用不是 B 类的 m() 方法(这适用于 super.m()),而是 C 类。

如果有帮助,这是我的实际代码:

    @Override
public void m() {

    if(this.au() && this.getGoalTarget() != null && this.vehicle instanceof EntityChicken) {
        ((EntityInsentient) this.vehicle).getNavigation().a(this.getNavigation().j(), 1.5D);
    }

    try {
        ((EntityMonster) this.getClass().getSuperclass().getSuperclass().getConstructor(World.class).newInstance(this.world)).m();
    }catch(InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e){
        e.printStackTrace();
    }

}

【问题讨论】:

  • 你说你的B类方法已经调用了超级(C)方法。你还想要什么?
  • 这听起来有点令人困惑,所以A extends B 扩展了C - 足够了;并且m()B 中的方法super.m() 有类似super.m() 的东西 - 它调用C 类的方法m() - 我不明白你说什么问题出在哪里?即使您重写了基类 (C.m()) 的方法,也没有什么能阻止您使用子类(B)中的super.m() 调用该方法。
  • 啊,我想我没有很好地解释安静。我只是在我的 C 类中覆盖 B 类的方法。从那里,在我的 C 类方法中,我需要调用不是 B 类的 m() 方法(这适用于 super.m()),而是 C 类。
  • 您的编辑似乎自相矛盾。你有一个C 基类,它由B 扩展,最后你有一个A 扩展B。从一般到特殊,C -> B -> A。但是,在您的编辑中,您说您正在覆盖C 中的方法m(),这没有意义,因为它是基类。请澄清。
  • @FedericoPeraltaSchaffner 不,我是说,从 C 类开始,我正在重写 B 类中的 m() 方法。

标签: java inheritance bukkit


【解决方案1】:

如果你不能使用继承,那么你应该给decorator pattern一个机会。

在动机部分:

...有时(例如,使用外部框架)修改基类是不可能的、合法的或方便的。

在您的情况下,您可以使用装饰器模式向C 类(继承自B 的类)添加功能:

class A {
    public void m() {
        System.out.println("A");
    }
}

class B extends A {
    public void m() {
        System.out.println("B");
    }
}

class C extends B {

    private final A base;

    public C(A base) { // pass other needed arguments
        this.base = base;
    }

    public void m() {
        this.base.m(); // instead of super.m()
        System.out.println("C");
    }
}

您需要按如下方式实例化 C

A base = new A();
C c = new C(base);

然后:

c.m();

应该打印的内容:

A
C

【讨论】:

  • 很遗憾,我做不到。也许我第一次应该更好地解释它......我正在使用 Bukkit,而我实际上想要做的是创建一个旨在替换默认实体的自定义实体。虽然默认的类仍然存在,但我告诉 Bukkit 只使用我的类而不是那个类。另外,我的类继承了默认类的所有行为,但它增加了一些东西。无论如何,问题是,我不是实例化我的类的人,Bukkit 是。而且它只能用默认僵尸类(世界)的普通参数来实例化它......
【解决方案2】:

你想这样称呼它吗?

public class C {

    public void m() throws IllegalAccessException, InstantiationException {
        System.out.println("C");
    }
}

public class B extends C {
    @Override
    public void m() throws IllegalAccessException, InstantiationException {
        super.m();
        System.out.println("B");
    }
}

public class A extends B {
    @Override
    public void m() throws IllegalAccessException, InstantiationException {
        ((C) this.getClass().getSuperclass().getSuperclass().newInstance()).m();
        System.out.println("A");
    }
}

【讨论】:

  • 嗯,让我看看,我现在会检查它是否有效,但是是的,这就是我理论上想要做的。不过,使用反射从来都不是难事。
  • 啊,不幸的是,它在我的情况下不起作用。我得到一个实例化异常:hastebin.com/secepakexo.avrasm
  • 你支持默认构造函数吗?
  • 否则您可能需要使用Activator。见activator
  • 正如您在我上一条评论中看到的那样,我没有使用任何 args 构造函数,但我自己编辑了它。这仍然会引发异常......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
  • 2013-10-24
  • 1970-01-01
  • 1970-01-01
  • 2012-08-09
  • 1970-01-01
  • 2012-05-01
相关资源
最近更新 更多