【问题标题】:How to find what instance a method returns? Java-programming如何找到方法返回的实例? Java 编程
【发布时间】:2011-06-14 08:48:16
【问题描述】:

如果我有这样的对象:

Teacher extends Person
Student extends Person

然后,我在服务中有一个函数,它返回人员列表/数组等,但列表中的某些项目可能是教师,有些可能是学生。

在返回端,我希望用户能够检查每个元素的实例以确定它是学生还是老师。

构建此代码的最佳方式是什么。

所以,在服务中我想要这样的东西:

public LinkedList<Person> getPersonByID(List<String id>);

【问题讨论】:

    标签: java inheritance casting polymorphism instanceof


    【解决方案1】:

    最好的方法是使用多态性来消除显式检查 Person 类型的需要。具体怎么做,取决于你的任务,也许你可以提供更多代码。

    【讨论】:

    • 是的,我也认为正确的模式很大程度上取决于您打算如何处理这些信息。按照其他 cmets 中的说明坚持使用 instanceof 现在可能会很好,但我相信您很快就会发现重构的需要,并希望做一些更灵活的事情。
    【解决方案2】:

    这可以解决没有instanceof 使用visitor pattern。 (如果使用普通的多态技术无法解决问题,则可能首选这种方法,因为instanceof should be avoided。)

    这是我的答案over here 的改编,带有demo on ideone.com

    import java.util.*;
    
    public class Test {
    
        public static void main(String[] args) {
    
            List<Person> somePersons = new LinkedList<Person>();
    
            somePersons.add(new Teacher());
            somePersons.add(new Student());
            somePersons.add(new Teacher());
    
            for (Person p : somePersons)
                p.visit(new Visitor() {
                    @Override
                    public void accept(Student student) {
                        student.learn("stuff");
                    }
    
                    @Override
                    public void accept(Teacher teacher) {
                        teacher.teach("some other stuff");
                    }
                });
        }
    }
    
    
    interface Visitor {
        public void accept(Teacher a);
        public void accept(Student b);
    }
    
    abstract class Person {
        String name;
        abstract void visit(Visitor v);
    }
    
    class Teacher extends Person {
    
        public void teach(String toTeach) {
            System.out.println("I'm teaching " + toTeach);
        }
    
        public void visit(Visitor sv) {
            sv.accept(this);
        }
    }
    
    class Student extends Person {
    
        public void learn(String toLearn) {
            System.out.println("I'm learning " + toLearn);
        }
    
        public void visit(Visitor sv) {
            sv.accept(this);
        }
    }
    

    【讨论】:

      【解决方案3】:

      Java 中有一个instanceof关键字,可以在运行时用于检查对象的类型。所以,读起来像这样的代码:

      LinkedList<Person> foo = getPersonByID(some_id_list);
      for (Person p: foo)
         if (p instanceof Teacher)
            // do stuff
         else if (p instanceof Student)
            // again
         else
            // ...
      

      【讨论】:

      • InstanceOf 运算符的使用通常表示对多态性的错误使用。如果我们为 Person 引入新的角色,例如校长、家长、学校检查员、厨房工作人员、看守、秘书、助教——instanceof 运算符很快就会变得非常不可扩展,并且这种多重 if/else 实例检查的成本非常高。跨度>
      【解决方案4】:

      如果您知道以后需要更大的灵活性,您可以考虑从 is-a 关系转变为 has-a 关系。

      has-a 是一个人可以拥有的一组角色,例如教师角色或学生角色。或者两者兼而有之,比如学生正在讲课..

      展示这种方法的一个简单示例:


      public enum Role {TEACHER, STUDENT}
      

      public class Person {
      
          Set<Role> roles = new HashSet<Role>();
      
          public Person() {
            // a person does not have roles initially
          }
      
          public boolean addRole(Role aRole) {
            return roles.add(aRole);
          }
      
          public boolean hasRole(Role aRole) {
            return roles.contains(aRole);
          }
      
          // ...
      }
      

      public void someMethod(Person person) {
      
          if (Person.hasRole(Role.TEACHER)) {
            // do teacher stuff
          }
      
          if (Person.hasRole(Role.STUDENT)) {
            // do student stuff
            // Note: persons may be Teacher AND Student at the same time
          }
      
      }
      

      【讨论】:

        【解决方案5】:

        您始终可以使用以下代码检查给定实例是否为给定类型的类型

                if( selectedPerson instanceof Student)
                ...
        

        【讨论】:

          猜你喜欢
          • 2010-10-08
          • 2016-09-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-30
          • 2011-07-21
          相关资源
          最近更新 更多