Java 从列表中的对象获取原始类

Java 从列表中的对象获取原始类,java,Java,作为练习,我必须为游泳池编写一个非常简单的软件 父类是User 成人和儿童是扩展用户权限的两个类 DisabledChild和DisabledDult扩展用户并实现一个界面Disabled,只需使用一个额外的方法打印“我被禁用!” 大体上,我根据这些类的年龄参数和“禁用”布尔值创建它们的不同对象,然后将它们放入一个列表中,如下所示: public void insertData() { int age; Adult a = null; DisabledAdult da = nu

作为练习,我必须为游泳池编写一个非常简单的软件

父类是User

成人儿童是扩展用户权限的两个类

DisabledChildDisabledDult扩展用户并实现一个界面Disabled,只需使用一个额外的方法打印“我被禁用!”

大体上,我根据这些类的年龄参数和“禁用”布尔值创建它们的不同对象,然后将它们放入一个列表中,如下所示:

public void insertData()
{
   int age;
   Adult a = null;
   DisabledAdult da = null;
   Scanner scanIn = new Scanner(System.in);
   List l = new ArrayList();

  do {

   System.out.println("Insert user name, type 'quit' to exit");
   name = scanIn.next();

   System.out.println("Insert age");
   age = scanIn.nextInt();

        if (age > 16) {
            System.out.println("Is the adult disabled? ( y/n)");
            String disabled = scanIn.next();
            if("y".equals(disabled))
            {
               da = new DisabledAdult();
               l.add(da); // l is a list!
            } else
            {
               a = new Adult();
               l.add(a);
            }
        }

        else{
           // similar as above, but for children.
        }

    } while (!"quit".equals(name));

    scanIn.close();
        for (Object obj : l) {
              User u = (User) obj;
    }
问题来了:当我把东西放在列表中时,它们变成了对象,即使使用.getClass().getName(),我也无法返回到它们的原始类。所以我不能使用它们的特定方法,比如从禁用接口实现的方法

我被迫将Obj转换为用户(因为游泳池中的每个人都是用户),如下所示:

public void insertData()
{
   int age;
   Adult a = null;
   DisabledAdult da = null;
   Scanner scanIn = new Scanner(System.in);
   List l = new ArrayList();

  do {

   System.out.println("Insert user name, type 'quit' to exit");
   name = scanIn.next();

   System.out.println("Insert age");
   age = scanIn.nextInt();

        if (age > 16) {
            System.out.println("Is the adult disabled? ( y/n)");
            String disabled = scanIn.next();
            if("y".equals(disabled))
            {
               da = new DisabledAdult();
               l.add(da); // l is a list!
            } else
            {
               a = new Adult();
               l.add(a);
            }
        }

        else{
           // similar as above, but for children.
        }

    } while (!"quit".equals(name));

    scanIn.close();
        for (Object obj : l) {
              User u = (User) obj;
    }
但是我不能使用DisabledAdult或DisabledChild的额外方法,因为它们是在界面Disabled中定义的,而不是User

如果我这样做

obj.getClass().getName();
我可以看到它们的原始类,但只能访问对象方法

我想我可以做一些类似的事情:

if (obj instanceof Adult){
    Adult a = (Adult) obj;
}
if (obj instanceof Child){
    Child c = (Child) obj;
}
...
但它看起来很可怕,因为我应该检查每种类型的用户,如果他们被禁用或没有,等等

我能做什么


谢谢。

您应该这样声明您的列表,使用:

listl=newarraylist();

如果随后需要使用禁用的
界面的方法,则必须检查类型和强制转换。

您应该使用以下方式声明列表:

listl=newarraylist();
如果需要使用禁用的
界面的方法,则必须检查类型和类型转换。

用于列表。由于
l
中的所有对象都是
User
s,因此应将其指定为类型参数

而不是:

List l = new ArrayList();
使用:

这将允许您对禁用的用户执行禁用的特定操作。

用于您的列表。由于
l
中的所有对象都是
User
s,因此应将其指定为类型参数

而不是:

List l = new ArrayList();
使用:


这将允许您对禁用的用户执行特定于禁用的操作。

首先,您应该使用泛型,即
列表
,而不仅仅是
列表
。如果这是一门课,而你被教导要用过时的方式去做,那就找一个更好的老师

其次,以您描述的方式区分禁用和非禁用用户是非常糟糕的OO建模。通常,禁用的
用户
只是一个属性,而
用户
将具有类似
setDisabled()
isDiabled()
的方法。如果练习的目的是了解继承,您可能会使用类似于
descripbeself()
的方法,该方法在
User
中打印“我未被禁用”,并在
DisabledUser
中覆盖以打印其他内容。然后,您可以对这两种类型的实例调用此方法,而无需测试实际类并执行强制转换


我真诚地希望这个练习旨在教你什么不该做。

首先,你应该使用泛型,即
列表
,而不仅仅是
列表
。如果这是一门课,而你被教导要用过时的方式去做,那就找一个更好的老师

其次,以您描述的方式区分禁用和非禁用用户是非常糟糕的OO建模。通常,禁用的
用户
只是一个属性,而
用户
将具有类似
setDisabled()
isDiabled()
的方法。如果练习的目的是了解继承,您可能会使用类似于
descripbeself()
的方法,该方法在
User
中打印“我未被禁用”,并在
DisabledUser
中覆盖以打印其他内容。然后,您可以对这两种类型的实例调用此方法,而无需测试实际类并执行强制转换


我真诚地希望这个练习是为了教你什么不该做。

@Andreas你不必假设每个人都可以提前改变语言。有些人不得不使用Java,尤其是AP计算机科学领域的人。这是OO犯下的严重错误,而不是OO的案例。@KevinKrumwiede请看我对你答案的评论。@damryfbfnetsi十二年前,你会对用C学习指针算术说同样的话吗?为什么我们要教我们的孩子上个十年的技术。当然孩子需要用Java完成这项工作,但我鼓励他寻找一种日常逻辑优雅的语言。@Andreas你不必假设每个人都可以提前改变语言。有些人不得不使用Java,尤其是AP计算机科学领域的人。这是OO犯下的严重错误,而不是OO的案例。@KevinKrumwiede请看我对你答案的评论。@damryfbfnetsi十二年前,你会对用C学习指针算术说同样的话吗?为什么我们要教我们的孩子上个十年的技术。当然孩子需要用Java完成这项工作,但我鼓励他寻找一种日常逻辑优雅的语言。这是一种折衷。有时,您可能希望实现某些只与某些类型的对象相关的方法,而将它们更改为属性意味着您必须在所有对象中实现它们,并将它们从编译时更改为运行时检查。在这种情况下,您几乎应该始终将这些子类的实例作为这些子类的实例来处理。除了
equals(…)
方法之外,测试对象实际类型的合法理由非常少。这是一种折衷。有时,您可能希望实现某些只与某些类型的对象相关的方法,并将其更改为