有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

继承Java通过设计避免实例

考虑下面的课堂设计:

public class SuperType { };
public class SubType1 extends SuperType { };
public class SubType2 extends SuperType { };
public class SubType3 extends SuperType { };

public class Tuple {
    SuperType t1;
    SuperType t2;

    public Tuple(SuperType t1, SuperType t2) {
        this.t1 = t1;
        this.t2 = t2;
    }

    public void DoSomething1() {
        if((t1 instanceof SubType1) && (t2 instanceof SubType3))
            switch(t1, t2);
        else if((t1 instanceof SubType2) && (t2 instanceof SubType1)) 
             t1.DoSomething();
        else if( ... ) {
             t1.DoSomething();
             t2.DoSomething();
        }
        else if( ... )
            // ...
    }

    public void DoSomething2() {
        // basically the same
    }
}

由于操作依赖于两种类型,我无法通过将方法移动到子类型来避免instanceof操作符。有没有一种方法可以改进我的设计,从而避免使用instanceof

我知道这里有很多类似的问题,但我想避免使用访问者,因为我有大约20个DoSomething()方法,这些方法将导致9*20个visit()实现


共 (2) 个答案

  1. # 1 楼答案

    这里有一个简单的解决方案选项,您可以使用它,将Generics用于类型safe&Polymorphism在每个子类中执行操作行为

    interface SuperType<T> { void doAction(); };
    class SubType1 implements SuperType<SubType1> { public void doAction(){} };
    class SubType2 implements SuperType<SubType2> { public void doAction(){} };
    class SubType3 implements SuperType<SubType3> { public void doAction(){} };
    
    class Tuple {
    
       //if((t1 instanceof SubType1) && (t2 instanceof SubType3))
       //passing params rather than instanceof checking
       public void doSomething1CaseOne(SuperType<? extends SubType1> t1, SuperType<? extends SubType3> t3) {
           if(t1 == null || t3 == null) {
               throw new NullPointerException("Null Params!");
           }
           /**
            * the method action here
            * example: switch(t1, t2);
            */
       }
    
       //if((t1 instanceof SubType2) && (t2 instanceof SubType1))
       public void doSomething1CaseTwo(SuperType<? extends SubType2> t2, SuperType<? extends SubType1> t1) {
           if(t2 == null || t1 == null) {
               throw new NullPointerException("Null Params!");
           }
           /**
            * the method action here
            * example: t1.doAction();
            */
       }
       ... others methods
    }
    

    下面是向方法传递有效/无效参数的示例:

    Tuple tuple = new Tuple();
    SuperType<SubType1> t1 = new SubType1();
    SuperType<SubType2> t2 = new SubType2();
    SuperType<SubType3> t3 = new SubType3();
    
    tuple.doSomething1CaseOne(t1, t3); //valid typesafe compilation time
    tuple.doSomething1CaseOne(t1, t2); //invalid typesafe compilation time
    
    tuple.doSomething1CaseTwo(t2, t1); //valid typesafe compilation time
    tuple.doSomething1CaseTwo(t1, t2); //invalid typesafe compilation time
    
  2. # 2 楼答案

    在OO语言中实现这一点的正确方法是使用一种称为“双重分派”的模式(Googlable,但wikipedia的页面并不好)

    “append”方法就是一个很好的例子:

    class Super
    {
        abstract void appendTo(Super target);
        abstract void append(Sub1 source);
        abstract void append(Sub2 source);
    }
    
    class Sub1
    {
        void appendTo(Super target)
        {
            target->append(this); //calls the Sub1 overload
        }
        void append(Sub1 source)
        {
            ... this is Sub1, source is Sub1 ...
        }
        void append(Sub2 source)
        {
            ... this is Sub1, source is Sub2 ...
        }
    }
    class Sub2
    {
        void appendTo(Super target)
        {
            target->append(this); //calls the Sub2 overload
        }
        void append(Sub1 source)
        {
            ... this is Sub2, source is Sub1 ...
        }
        void append(Sub2 source)
        {
            ... this is Sub2, source is Sub2 ...
        }
    }