【问题标题】:Java : Using parent class method to access child class variableJava:使用父类方法访问子类变量
【发布时间】:2012-07-04 12:06:08
【问题描述】:

我有以下情况:

public class A {

    private int x = 5;

    public void print()
    {
        System.out.println(x);
    }
}


public class B extends A {

    private int x = 10;

    /*public void print()
    {
        System.out.println(x);      
    }*/

    public static void main(String[] args) {
        B b = new B();
        b.print();
    }

}

执行代码时,输​​出为:5。

如何通过父类方法访问子类(B's)变量(x)?

这是否可以在覆盖 print() 方法(即在 B 中取消注释)的情况下完成?

[这很重要,因为在重写时我们将不得不再次重写 print() 方法的整个代码]

已编辑

更多说明:-

  • 问题的动机是使用来自其父类方法的子类私有变量的值。这不需要更改父类私有变量的值即可达到预期的结果。
  • 不过,这里发布的答案让我得到了我想要的答案,我在下面发布了。

(感谢大家的时间和帮助)

【问题讨论】:

  • 当你想打印B的变量x时,你是想让x和A的x不同,还是应该一样?
  • @WeiHao 从代码中很明显A 中的x 是5,B 中的一个是10。他希望B.print() 输出10,因为他对输出 5 不满意。因此他希望它们有所不同。
  • @Jayant 这不是关于父母没有信息,它没有。问题是x 的值在创建B 期间没有被覆盖。
  • 我主要担心的是,这里父类中的代码不能被子类重用。这段代码可以重复使用吗?
  • @Jayant 父类中的代码可以重用,看看我的回答:)。您的问题是 x 的值在创建 B 时没有更新,因为默认值只评估一次。

标签: java oop inheritance


【解决方案1】:
class A {
    private int x = 5;

    protected int getX() {
        return x;
    }

    protected void setX(int x) {
        this.x = x;
    }

    public void print() {
        // getX() is used such that 
        // subclass overriding getX() can be reflected in print();
        System.out.println(getX());
    }
}

class B extends A {
    public B() {
        // setX(10);  // perhaps set the X to 10 in constructor or in main
    }

    public static void main(String[] args) {
        B b = new B();
        b.setX(10);
        b.print();
    }
}

已编辑

以下是使用抽象类和方法解决类似场景的一般答案:

abstract class SuperA {
    protected abstract Object getObj();

    public void print() {
        System.out.println(getObj());
    }
}

class A extends SuperA {
    @Override
    protected Object getObj() {
        // Your implementation
        return null; // return what you want
    }
}

class B extends A {
    @Override
    protected Object getObj() {
        // Your implementation
        return null; // return what you want
    }

    public static void main(String[] args) {
        B b = new B();
        b.print();
    }
}

【讨论】:

  • 不错的全方位解决方案。这很 OOP =D。此外,非常类似于 C#。
  • @Shingetsu,谢谢,但我对 C# 一无所知,我打算学习它,但我的工作不允许......
  • 基本上,C# 只是 Java 的优雅版本。如果您已经很了解 Java,那么学习它不会有太大的困难,尽管了解 .NET 和 C++ 会派上用场 =D。
  • 这会很好用。但它实际上击败了问题的动机。需要的是在父类函数中使用子类中的变量值。
  • 然后你可以重写 getX() 方法并返回所需的值。
【解决方案2】:

阅读此处发布的所有答案后,我得到了我想要的东西。以下是我认为对我的问题最好的答案:

public class A {
    private int x = 5;    
    protected int getX(){
        return x; 
    }    
    public void print(){
        System.out.println(getX());
    }
}
public class B extends A {
    private int x = 10;
    protected int getX(){
        return x; 
    }  
    public static void main(String[] args) {
        B b = new B();
        b.print();
    }
}

设置一个受保护的 getter 并重写它比重写 print() 方法本身要好,因为可能有任何其他巨大的方法代替 print 方法,它可能需要访问子类变量的值(s )。

【讨论】:

  • @kakacii 是的,虽然 VictorWong 的回答没有准确回答这个问题,但人们发现它更有用。我改变了我的选择。谢谢:)
  • @Jayant 我看不出我的一般解决方案(不是第一个,而是编辑过的)与您在此处的答案之间有任何区别,除非您将 obj 替换为 x。无意冒犯,但我想知道为什么我的解决方案不够精确。
【解决方案3】:

要解决您的问题,您必须在父类 A 中定义字段,如受保护(因此它将在子类上继承)并在子类 B 的构造函数中设置字段值 x。打印方法是也继承自 A 类,因此您可以直接从父类调用它。

希望对你有帮助。

public class A 
{
    // fields declaration 
    protected int x = 5;

    public void print()
    {
        System.out.println(x);
    }
}



public class B extends A 
{

    public B()
    {
        // set child x value. The field have been defined in the parent class
        x = 10;
    }

    public static void main(String[] args) 
    {
        A a = new A();
        a.print(); // print 5

        B b = new B();
        b.print(); // print 10
    }

}

【讨论】:

    【解决方案4】:

    您可以随时将其添加到构造函数中:

    public class B extends A {
    
        //this line is unnecessary: private int x = 10;
    
        /*public void print()
        {
            System.out.println(x);      
        }*/
    
        public B()
        {
            x=10;
        }
    
    
        public static void main(String[] args) {
            B b = new B();
            b.print();
        }
    
    }
    

    在您尝试时它不起作用的原因是默认值只被评估一次。因此,当它在 A 中默认为 5 时,即使您在 B 中使用默认 10,它仍保持为 5。

    【讨论】:

    • 首先,如果 x 的可见性是私有的,则在 B 的构造函数中更改 x 将不起作用。其次,即使我们使 x 的可见性受到保护,它也会改变父类中变量 x 的值。需要的不是改变父类中变量的值,而是使用子类变量的值。
    • @Jayant 子类变量不存在。你在父级中创建一个变量,给它一个默认值。默认值评估一次。您在 B 中为 THE SAME VARIABLE 提供了另一个默认值,但默认值已在 A 中进行了评估。当您创建B 时,IL 1st 在A 中评估x 的默认值,然后在B 中评估x,但由于x 已经在A 中评估,private int x = 10; 行绝对不会什么都没有。
    • 我不明白你想说什么。显然,B 类中的 private int x = 10 语句为 B 类中的变量 x 分配了一些新内存,它完全独立于 A 中的变量 x。
    • @Jayant 它并不完全独立于A 中的变量。恰恰相反,A 中的变量是私有的,因此是继承的。语句private in x = 10; 不会生成新变量 x。想象一下写作:public class A { private int x = 5; private int x = 10; }。没有意义?那是同样的情况。 私有字段被继承(但无法访问)。所以声明 private int x = 10; 实际上什么也没做。
    • @Jayant 您想在子类中创建一个全新的变量,或者只在父类中使用一个。没有“中间”。在第一种情况下,您必须更改名称。在后一种情况下,您必须对其进行保护。
    【解决方案5】:

    您应该为您想要的值公开一个 getter,并在子类中覆盖它。

    像这样:

    public class A {
    
        private int x = 5;
    
        public void print()
        {
            System.out.println(getX());
        }
    
        protected void setX(int x)
        {
            this.x = x;
        }
    
        protected int getX()
        {
            return x;
        }
    
    }
    
    
    public class B extends A {
    
        /*public void print()
        {
            System.out.println(x);      
        }*/
    
        public B()
        {
            setX(10);
        }
    
        public static void main(String[] args) {
            B b = new B();
            b.print();
        }
    
    }
    

    【讨论】:

    • 这也行得通,但如果 x 必须在某一时刻更改怎么办?这仅限于给出的示例。
    • 然后也做一个 X 的设置器。
    • @VictorWong 这不是真正的 getter,变量实际上并不存在。
    • 这是一个很好的答案(解决了问题)。声明私有变量并在 getX() 方法中返回它而不是直接返回值会很好。如果您允许,我可以编辑您的答案以执行上述操作(并接受)。
    • 我更新了答案以提供子类在其构造函数上使用的设置器。这应该具有相同的效果。
    猜你喜欢
    • 1970-01-01
    • 2020-02-13
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    • 2012-10-28
    • 1970-01-01
    相关资源
    最近更新 更多