当前位置: 首页 > 知识库问答 >
问题:

此代码是否可以考虑用于Java的成员覆盖?

程皓轩
2023-03-14

理论上,Java不支持成员重写,所以我想这个代码片段是否可以用于重写类的成员。但是,我不太确定在什么情况下这段代码可能会失败。我的意思是,如果这是完美的,它不会被忽视的,对吧?这可能是一个愚蠢的问题,但我真的很想知道,在我的头脑想不到的不同情况下,这段代码可能会做些什么。所以如果有人能给我解释一下就真的很棒了。谢谢!


    class ClassA{
        int i = 10;
        void eat() {
            System.out.println("In Class A: Eating");
        }
        void bark() {
            System.out.println("In Class A: Barking");
        }
    }
    class ClassB extends ClassA{
        //int i = 20;
        ClassB(){
            super.i = 20; //Changing the value of i in class A.
        }
        void eat() {
            System.out.println("In Class B: Eating");
        }
            
    }
    public class Main{
        public static void main(String[] args) {
            ClassB b = new ClassB();
            System.out.println(b.i);
            b.eat();
            b.bark();
            ClassA ua = new ClassB();
            System.out.println(ua.i);
            ua.eat();
            ua.bark();
            ClassA a = new ClassA();
            System.out.println(a.i);
        }
    }

 

共有2个答案

范成周
2023-03-14

如果您重写了一个方法,然后尝试从父级调用它,则父级调用派生方法,即使它在定义时并不知道它。

class A {
  public void foo() {
    System.out.println("A.foo");
  }
  public void callFoo() {
    this.foo();
  }
}

class B {
  public void foo() {
    System.out.println("B.foo");
  }
}

B instance = new B();
instance.callFoo(); // Prints "B.foo"

现在,如果我们尝试对实例字段做同样的事情,我们得到的是原始字段。

class A {
  public String foo = "A.foo";
  public void printFoo() {
    System.out.println(this.foo);
  }
}

class B {
  public String foo = "B.foo";
}

B instance = new B();
instance.printFoo(); // Prints "A.foo"

所以我们实际上没有覆盖任何内容;我们只是创建了一个新变量,它碰巧与现有变量的名称共享,令人困惑。如果它是真的重写,那么我们将能够增强a方法的行为,这些方法使用该变量但不知道子类。

贲言
2023-03-14

我不太确定在什么情况下这段代码可能会失败。

它(某种程度上)在人类读者/概念层面上是失败的。

Java语就是它的本来面目。这意味着Java程序员知道应该期待什么,应该做什么,不应该做什么。

继承的基本规则之一(在Java中,但在一般情况下也是如此):对于超类的字段要非常谨慎。成员字段应被视为类的内部实现细节。你不把它暴露在外面的世界。你不会把它暴露给你的孩子类,除非有一个真正好的理由这么做。如果您真的想在Java中这样做,那么正确的方法是:对该字段使用protected关键字。

您的想法基本上是子类“知道”超类字段,更糟的是:在创建时改变“内部状态”。

因此,在现实世界中,这样的代码可能会很快导致各种令人讨厌的意外。因为现实世界中的人们不会想到一个子类正在做类似的事情,因此他们在调试一个大型应用程序中的问题时可能真的很惊讶地发现“我应该是10,为什么是20”。

长话短说:你能做的事实并不意味着你应该去做。恰恰相反:好的编程是以“标准”的方式做事,不会让你的读者感到惊讶。

 类似资料:
  • Jooq-3.13 我们使用Jooq Codegen使用生成策略进行生成。 如果在(department_id,employee_number)上有一个复合唯一键,那么我想要一个方法。这可能吗?(显然,我可以为此使用自己的方法,但我们有很多这样的约束,自动生成的方法将非常有用)

  • 问题内容: 现在我有了一些C源代码,我想在我的Java应用程序中使用它。我需要执行C源代码,并将结果返回到我的Java应用程序。与其将所有C源代码重写为Java,我如何在Java应用程序中重用C源代码? 问题答案: 看一下Java Native Interface 。 Java本机接口(JNI)是一种编程框架,它使Java虚拟机(JVM)中运行的Java代码能够被本机应用程序(特定于硬件和操作系统

  • 问题内容: 我正在评估JOOQ是否可在仍在开发中的新系统中使用。我想避免在与应用程序一起开发数据库时生成代码,而只是为该应用程序起持久存储的作用。因此,预计数据库模式定义将由Java代码(java中的表定义)驱动。 JOOQ是否适合上述用例?是否有用于模式定义的Java DSL? 问题答案: JOOQ是否适合上述用例? 是的,许多jOOQ用户仅使用运行时库,而没有代码生成器。入门指南中提供了示例。

  • 我正在评估JOOQ在一个仍在开发中的新系统中的使用情况。当数据库与应用程序一起开发时,我希望避免代码生成,而只是在这个应用程序中扮演持久存储的角色。因此,数据库模式定义应该由Java代码(Java中的表定义)驱动。 JOOQ是否适用于上述用例?是否有用于模式定义的JavaDSL?