java - 如何在 Java 中从没有 Instanceof 的父类的方法中确定子类的类型
问题描述
以下代码运行,但我的实现违反了 SOLID 原则。我希望有人可以帮助我重新设计我的代码,使其遵循 SOLID 原则,特别是避免使用instanceof
.
我有一个父类 ,Parent
有三个子类:Element
、Container
和Wrapper
。
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());
}
}
解决方案
推荐阅读
- django - 如何在视图 Django 中接收 AJAX POST 数据?
- javascript - Jquery 函数显示隐藏无法正常工作
- android - Android 的 Jenkins 流水线失败
- c# - EF Core 内存数据库在测试更新操作时生成 System.InvalidOperationException
- javafx-11 - 如何让拼写检查器在 javafx11 webview 上工作
- python - request.POST 始终为空
- php - 如何使用 sylius 1.10 扩展客户/商店用户注册?
- c# - 在用户登录后将按钮更改为可见
- android-studio - 从对话框片段中的 MainActivity 中运行方法
- machine-learning - 混淆矩阵轴的正确标注