Java 我可以合理地访问扩展类的变量吗?

Java 我可以合理地访问扩展类的变量吗?,java,inheritance,extends,Java,Inheritance,Extends,我有一个来自我创建的一个类的对象数组,其中包括该类型的对象和扩展第一个对象的对象。我想访问一个变量,当我知道我所说的对象是扩展对象时,扩展对象具有第一个对象没有的变量。这方面的简化示例如下所示: public class Parent { public boolean isChild=false; } public class Child extends Parent { public int i=5; public Child() { isChild=

我有一个来自我创建的一个类的对象数组,其中包括该类型的对象和扩展第一个对象的对象。我想访问一个变量,当我知道我所说的对象是扩展对象时,扩展对象具有第一个对象没有的变量。这方面的简化示例如下所示:

public class Parent {
    public boolean isChild=false;
}

public class Child extends Parent {
    public int i=5;
    public Child() {
        isChild=true;
    }
}

public class main {
    public static void main(String[] args) {
        Parent x=new Child();
        if (x.isChild) {
            System.out.println(x.i); //this is what I want to do...
            //... but I get an error because Parent doesn't have a variable called i.
        }
    }
}
那么,有什么办法让我绕过这件事吗?我考虑制作一个受保护的静态变量,但这似乎不是我想要的,因为我需要它的多个副本

好的,至于这实际上是如何被使用的,我第一次为了好玩而编写自己的计算机编程语言时没有包括在内。我有一个已经创建的对象的ArrayList,允许这种语言的用户创建他们自己的对象,也可以使用我用java代码和我的语言代码创建的对象


我在java中创建了字符串aka child,并让它们扩展我的wafl_对象类父对象。通过这种方式,它们可以在ArrayList中进行循环,而无需为我创建的每个对象使用不同的数组。然而,我想接受一个字符串作为另一个类的参数,我看不到它的值,因为它在一个对象数组中,我把它当作一个对象。我现在已经解决了这个问题,将它转换为字符串,一旦我知道它确实是一个字符串,然后查看它的值。在这种情况下,投下它更容易,但在其他情况下,禁欲可能更有用。

试试以下方法:

if(x instanceof Child){
    System.out.println(((Child)x).i);
}
首先,可以使用instanceof代替isChild:if x instanceof Child。之后,您可以安全地将x投射到Child:Child childX=childX。然后,childX允许您访问x

通常,不赞成检查类型。通常,您应该设计您的函数,使它们接受一个足够通用的类型,以便在不必强制转换为派生类类型的情况下执行所有需要执行的操作。

您不需要isChild变量。可以使用if x instanceof Child。但为了访问i,您必须将案例x传递给Child

此外,不要直接访问成员。像我这样的数据成员应该是私有的,您应该通过getter访问它们

public class main {
    public static void main(String[] args) {
        Parent x=new Child();
        if (x instanceof Child) {
            System.out.println((Child)x.getI());
        }
    }
}

使用多态性,而不是测试对象的类型:

public abstract class Parent {
    public abstract int getValue();
}

public class Child extends Parent {
    @Override
    public int getValue() {
        return 5;
    }
}

public static void main(String[] args) {
    Parent x = new Child();
    System.out.println(x.getValue());
}

没有理由使用parent或child

public class main {
    public static void main(String[] args) {
        Parent x=new Child();
        if (x.isChild) {
            System.out.println(((Child)x).i); //this is what I want to do...
            //... but I get an error because Parent doesn't have a variable called i.
        }
    }
}

首先,前面的答案是正确的,并且大致相同。您必须让编译器知道您希望将x用作子级而不是父级

因此,根据您的代码示例,答案是将System.out语句修改为以下内容:

 System.out.println(((Child)x).getValue());
您可以使用instanceof和cast解决这个问题,如其他答案中所述,但通常最好使用多态性来定义子类可以重写的方法。具体方法取决于您的程序的具体性质,但这里有一种可能性,我使用Employee作为家长,HourlyEmployee作为子构造函数,需要填写其他逻辑:

public class Employee {
    private String name;
    public String getDescription() {
        return name;
    }
}

public class HourlyEmployee {
    private int wage;
    @Override
    public String getDescription() {
        return super.getDescription() + " [at $" + wage + " per hour]";
    }
}

那么使用Employee的类就不需要测试它是否是HourlyEmployee;它只调用getDescription,该方法将或不将小时工资包含在结果中,这取决于它是什么类

有几个答案告诉您如何使用instanceof和casting to Child实现这一点,但在现实生活中,类代表实际的概念,而不仅仅是父类和子类,这几乎肯定会被认为是一个糟糕的设计,建议改用多态性。但是,最好的确切方法取决于实际使用情况。这里的用例是什么?还是只是语言好奇?@ajb抱歉之前没有回答,没有注意到这些评论。。。我制作自己的计算机编程语言只是为了好玩,并且拥有一个包含所有存在对象的数组。我还在java中创建了一些类似数组和字符串的对象,需要访问我创建的类似字符串的类的值。因为它是一个对象,我可以在ArrayList中与所有其他对象一起携带它,但它是唯一一个具有字符串值的对象,所以这只是一次性的事情。为什么在我已经回答了它并且正在改进答案之后,你才删除你的?我们中的大多数人都不喜欢浪费时间去帮助别人,只是看着自己的答案消失。似乎nikpon在我写我自己的答案时回答了这个问题。这是sameThank you的建议,但它不适用于我的特殊情况。我的数组中有父类和子类的实例,这意味着如果我将父类抽象化,我将无法使用它。请将其设置为返回默认值,或者设置为null。返回类型必须更改为整数,或者引发异常。添加一个公共布尔hasValue方法,父对象返回false,子对象返回true。或者使用访问者模式。有许多解决方案是c
使用多态性而不是脏类型检查。啊,协变arrays@WiErD0,如果您的数组中有父级的其他子级,您将如何处理?我认为重新思考您的解决方案会使您受益。@WiErD0如果您能在您的问题中提供更完整的用例描述,您在这里提到的是相对于对象的精灵,人们会更好地回答您的问题谢谢您的回答。虽然X.L.Ant和Eran都有相似的回答,给出了相同的想法,但我发现你的回答最具描述性。我也从来没有想过铸造对象,我不知道人们可以对灵长类数据类型以外的其他对象进行铸造,我仍然不知道它是如何工作的。