英文:
How to make Java class know what to extend?
问题
请提供要翻译的文本,我会尽力为您提供翻译。
英文:
Assume we have three classes, Parent
, Child1 extends Parent implements ISomething
and Child2 extends Parent implements ISomethingElse
. Now, I want to make Child3
, which will either extends
Child1
or Child2
depending on what Child3
receives.
The Child3
constructor is something like this:
public <T extends Parent> Child3(T child) {}
How can I make Child3
know which class to extend?
(Don't answer Parent
. Assume extending Parent
will break the code and Parent
doesn't implement anything)
答案1
得分: 1
You mentioned ISomething and ISomethingElse, which indicates that you want different features, capabilities, possibly combined, for Child classes.
In that case inheritance is unsuitable.
class Parent {
// Untyped but safe.
private Map<Class<?>, Object> capabilities = new HashMap<>();
protected <I> void register(Class<I> intf, I obj) {
capabilities.put(intf, obj);
}
public <T> Optional<T> lookup(Class<T> intf) {
Object obj = capabilities.get(intf);
return obj == null ? Optional.empty() : Optional.of(intf.cast(obj));
}
}
interface Flying {
void fly(double altitude);
}
Parent pelican = new Pelican();
Flying flying = pelican.lookup(Flying.class).orElse(null);
flying.fly(0.5);
pelican.lookup(Swimming.class).ifPresent(
swimming -> swimming.swim(true);
);
class Bird extends Parent { ... } // With Swimming capability
class Pelican extends Bird {
public Pelican() {
register(Swimming.class, new Swimming() {
@Override public void swim(boolean atSurface) { ... }
});
}
}
This is more versatile and more dynamic. But one might want:
class Pelican extends Bird implements Swimming {
@Override
public void swim(boolean atSurface) {
return lookup(Swimming.class).get().swim(atSurface);
}
}
In your case, you seem to want an object either has ISomething or ISomethingElse, so this would be a solution.
If all this seems too much overhead, consider delegation:
class Pelican extends Bird implements Swimming {
private final Swimming swimmer = new SwimmingImplementation(this);
@Override
public void swim(boolean atSurface) {
return swimmer.swim(atSurface);
}
}
Pelican actually delegates to a Swimming implementation.
英文:
You mentioned ISomething and ISomethingElse. Which indicates that you want different features, capabilities, possibly combined, for Child classes.
In that case inheritance is unsuitable.
class Parent {
// Untyped but safe.
private Map<Class<?>, Object> capabilities = new HashMap<>();
protected <I> void register(Class<I> intf, I obj) {
capabilities.put(intf, obj);
}
public <T> Optional<T> lookup(Class<T> intf) {
Object obj = capabilities.get(intf);
return obj == null ? Optional.emtpy() : Optional.of(intf.cast(obj));
}
}
interface Flying {
void fly(double altitude);
}
Parent pelican = new Pelican();
Flying flying = pelical.lookup(Flying.class).orElse(null);
flying.fly(0.5);
pelical.lookup(Swimming.class).ifPresent(
swimming -> swimming.swim(true);
);
class Bird extends Parent { ... } // With Swimming capability
class Pelican extends Bird {
public Pelican() {
register(Swimming.class -> new Swimming() {
@Override public void swim(boolean atSurface) { ... }
});
}
}
This is more versatile and more dynamic. But one might want:
class Pelican extends Bird implements Swimming {
@Override
public void swim(boolean atSurface) {
return lookup(Swimming.class).get().swim(atSurface);
}
}
In your case, you seem to want an object either has ISomething or ISomethingElse, so this would be a solution.
If all this seems too much overhead, consider delegation:
class Pelican extends Bird implements Swimming {
private final Swimming swimmer = new SwimmingImplemetation(this);
@Override
public void swim(boolean atSurface) {
return swimmer.swim(atSurface);
}
}
Pelican actually delegates to a Swimming implementation.
答案2
得分: 0
你不能。继承结构在编译时定义(除非你使用魔法)。
你需要创建两个类,并将你的构造函数替换为工厂方法(或一对工厂方法)。
附注:如果可能的话,你可以考虑用委托代替继承。
英文:
You can't. Inheritance structure are defined at compile time (unless you use magic).
You have to create two classes and replace your constructor with factory method (or pair of factory methods).
PS: You may consider replacing inheritance with delegation if it possible.
答案3
得分: 0
你可以优先使用组合而不是继承:
public class Parent {}
public interface ISomething {}
public interface ISomethingElse {}
public class Child1 extends Parent implements ISomething {}
public class Child2 extends Parent implements ISomethingElse {}
// Child 3 does not inherits from other classes
public class Child3<T extends Parent> {
private final T child;
public Child3(T child) {
this.child = child;
}
public T getChild() {
return this.child;
}
}
// Consumer checks the type of the contained value.
// If you don't want to check types, you can
// create adapter classes for each subclass of the parent
public class Consumer {
public void test(Child3 child3) {
if (child3.getChild() instanceof Child1) {
final Child1 child1 = (Child1) child3.getChild();
}
if (child3.getChild() instanceof Child2) {
final Child2 child2 = (Child2) child3.getChild();
}
}
}
英文:
You can prefer composition over inheritance:
public class Parent {}
public interface ISomething {}
public interface ISomethingElse {}
public class Child1 extends Parent implements ISomething {}
public class Child2 extends Parent implements ISomethingElse {}
// Child 3 does not inherits from other classes
public class Child3<T extends Parent> {
private final T child;
public Child3(T child) {
this.child = child;
}
public T getChild() {
return this.child;
}
}
// Consumer checks type of contained value.
// If you dont want to check types you can
// create adapter classes for each subclass of parent
public class Consumer {
public void test(Child3 child3) {
if (child3.getChild() instanceof Child1) {
final Child1 child1 = (Child1) child3.getChild();
}
if (child3.getChild() instanceof Child2) {
final Child2 child2 = (Child2) child3.getChild();
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论