在Java中如何从没有Instanceof的父类方法确定子类的类型

时间:2018-10-06 23:43:19

标签: java generics inheritance instanceof

以下代码可以运行,但是我的实现违反了SOLID原则。我希望有人可以帮助我重新设计代码,使其遵循SOLID原则,尤其是避免使用instanceof

我有一个父类Parent和三个子类:ElementContainerWrapper

Element仅包含一个整数,如数学标量。

Container有一个父数组Parent[] contents,它可以是任何子类,例如数学向量。它可以是标量(元素)的向量,向量(容器)的向量或函数(包装器)的向量。

Wrapper有一个接口Function,程序员可以为每个包装程序定义一个唯一的方法。例如,一个包装器可能包含一个将元素平方的函数,而另一个包装器可能包含一个在两个容器之间获取点积的函数。

Wrapper用两个通用类型Wrapper<Domain extends Parent,Range extends Parent>进行参数化,它们表示输入类型Domain和输出类型Range。

当我尝试访问Parent[] contents类中的Container数组时,出现了我的问题。由于内容可以是任何子类,并且每个子类对其add方法都有不同的定义,所以我发现自己不得不使用instanceof,这违反了SOLID原则。

如何更改代码的结构?

public class Parent {
    public Parent add(Parent p){return null;}
}

public class Element extends Parent{
    protected int value;
    public void set(int x){ value=x; }
    public int get(){ return value; }
    public Element(){ set(0); }
    public Element(int x){ set(x); }

    @Override
    public Parent add(Parent p){
        if (p instanceof Element){
            Element e = (Element) p;
            return add(e);
        }
        else if (p instanceof Container){
            Container c = (Container) p;
            return add(c);
        }
        else return null;
    }
    public Element add(Element e){ return new Element( get()+e.get()); }
    public Container add(Container c){ return c.add(this); }
}

///I would prefer for this class to be parameterized Container<Type>, but I run into the problem of instantiating generic arrays
public class Container extends Parent{
    protected Parent[] contents;
    public int length(){ return contents.length; }
    public Container(int x){ contents = new Parent[x]; }
    public void set(int k, Parent p){ contents[k]=p; }
    public Parent get(int k){ return contents[k]; }

    ///Have to use instanceof to determine which type of output it will be
    public Parent sum(){
        Parent p;
        if(get(0) instanceof Element)
            p = new Element();
        else if (get(0) instanceof Wrapper)
            p = new Wrapper();
        else p = new Parent();
        for(int k=0;k<contents.length;++k)
            p = p.add(contents[k]);
        return p;
    }

    ///Have to use instanceof to distinguish which add to use
    @Override 
    public Parent add(Parent p){
        if (p instanceof Element){
            Element e = (Element) p;
            return add(e);
        }
        else if (p instanceof Container){
            Container c = (Container) p;
            return add(c);
        }
        else return null;
    }
    ///adds element to the first entry in the container
    public Container add(Element e){
        Container out = new Container(contents.length);
        for(int k=0;k<contents.length;++k)
            out.set(k, contents[k]);
        out.set(0, out.get(0).add(e));
        return out;
    }
    ///adds component by component
    public Container add(Container c){
        int minLength;
        if(c.length() < contents.length)
            minLength = c.length();
        else minLength = contents.length;
        Container out = new Container(minLength);
        for(int k=0;k<minLength;++k)
            out.set(k, contents[k].add( c.get(k) ));
        return out;
    }
}

public interface Function <Domain extends Parent, Range extends Parent> {
    public Range of(Domain point);
}

public class ZeroFunction<Domain extends Parent,Range extends Parent> implements Function<Domain,Range>{
    @Override
    public Range of(Domain point) {
        return (Range) new Element();
    }
}

public class Wrapper<Domain extends Parent, Range extends Parent> extends Parent{

    protected Function<Domain,Range> function;
    public Wrapper(){ function = new ZeroFunction<Domain,Range>(); }
    public Wrapper(Function<Domain,Range> x) { function = x; }
    public Range of(Domain t){ return function.of(t); }

    @Override
    public Parent add(Parent p){
        if (p instanceof Wrapper)
            return add( (Wrapper) p);
        else return null;
    }
    public Wrapper<Domain,Range> add(final Wrapper<Domain,Range> w){
        return new Wrapper<Domain,Range>( new Function<Domain,Range>(){
            public Range of(Domain point){
                try{
                    Range term = function.of(point);
                    Range summand = w.of(point);
                    Range sum = (Range) term.add(summand);
                    return sum;
                } catch(Exception e){
                    e.printStackTrace();
                    return null;
                }
            }
        });
    }
}

public class Main {
    public static void main(String[] args){
        Wrapper<Container, Element> wrapper1 = new Wrapper<Container, Element>(new Function<Container, Element>() {
            @Override
            public Element of(Container c) {
                return (Element) c.sum();
            }
        });
        Wrapper<Container, Element> wrapper2 = new Wrapper<Container, Element>(new Function<Container, Element>() {
            @Override
            public Element of(Container c) {
                return (Element) c.sum();
            }
        });
        Container wContainer = new Container(2);
        wContainer.set(0, wrapper1);
        wContainer.set(1, wrapper2);

        Wrapper<Container,Element> wrapper3 = (Wrapper<Container,Element>) wContainer.sum();

        Container eContainer = new Container(2);
        eContainer.set(0, new Element(1));
        eContainer.set(1, new Element(2));

        Element solution = wrapper3.of(eContainer);

        System.out.println(solution.get());

    }
}

0 个答案:

没有答案