简而言之,我希望能够通过不实现某个接口的超类对类实例进行分组。但是从一组实例中,我想在实现该接口的那些实例上从接口调用方法。
可能解释它的一些示例代码。
class Building{
String c = "white";
Building(){
}
void printColor(){
println("The building is " + c);
}
void paint( String c ){
this.c = c;
}
void printBuildQuality(){
println("The build quality is average");
}
}
class SturdyFactoryBuilding extends Building implements Factory{
SturdyFactoryBuilding(){
super();
}
void printBuildQuality(){
println("The build quality is sturdy");
}
void printFactoryOutput(){
println("This factory makes stuff");
}
}
class ShakyFactoryBuilding extends Building implements Factory{
ShakyFactoryBuilding(){
super();
}
void printBuildQuality(){
println("The build quality is shaky");
}
void printFactoryOutput(){
println("This factory makes slightly different stuff");
}
}
public interface Factory{
public void printFactoryOutput();
}
Building building = new SturdyFactoryBuilding();
building.printBuildQuality();
building.printColor();
building.paint("bright red");
building.printColor();
building.printFactoryOutput();
我是否有办法实现这一目标,也许是通过拥有一个' isFactory'超级国旗。
感谢。
答案 0 :(得分:0)
我认为你必须做出权衡:要么你接受一些反模式,要么打开你Building
"界面"充当适配器:
class Building implements Factory{
// the other building stuff
@Override
public void printFactoryOutput(){ /* NO OP */ }
}
然后,您可以在所有printFactoryOutput
上致电Building
,直至此时无效。
由于您的Factory
- 实现扩展Building
,它们会自动继承NOOP实现。但是因为你覆盖了它:
class ShakyFactoryBuilding extends Building implements Factory{
ShakyFactoryBuilding(){
super();
}
@Override
public void printBuildQuality(){
println("The build quality is shaky");
}
@Override
public void printFactoryOutput(){
println("This factory makes slightly different stuff");
}
}
......你有理想的结果。
缺点当然是所有建筑物都有printFactoryOutput
可见。但那是我所说的权衡取舍。如果这是不可接受的,那么您必须完全重新考虑您的设计。
为了明确表示不工厂的建筑物不应被称为方法开启,你可以在建筑物中抛出UnsupportedOperationException,但这会强制你的代码中的try / catch块。您也可以返回一个布尔值:default = false并返回true,如果实际上是工厂......有很多可能性。
您也可以将设计更改为使用composition over inheritance。
答案 1 :(得分:0)
我认为你得到的消息是这是一个坏主意。它违反了普遍接受的面向对象设计原则。也就是说,有几种方法可以解决这个问题,有些方法比其他方式更糟糕。
最简单的事情就是这样:
if (building instanceof Factory)
((Factory)building).printFactoryOutput();
您需要检查它是否为Factory
,然后在投射后调用Factory
特定方法。它是实现糟糕设计的直接(因而易于理解)的方式。
Building
了解Factory
这有一个问题,即Building
和Factory
之间目前没有必要的关系,但这种关系可能对您有帮助。
class Building {
// ...
Factory adaptToFactory() {
return null;
}
}
class SturdyFactoryBuilding ... {
// ...
@Override
Factory adaptToFactory() {
return this;
}
}
同样适用于ShakyFactoryBuilding
。
然后你可以写
Factory f = building.adaptToFactory();
if (f != null)
f.printFactoryOutput();
如果你做了很多这样的事情,你可以把它变成你需要的地方。 (例如,Eclipse在整个地方使用适配器。)
interface Adaptable {
<T> T adapt(Class<T> clazz);
}
class Building implements Adaptable {
// ...
@Override
<T> T adapt(Class<T> clazz) {
if (clazz.isInstance(this)) {
return clazz.cast(this);
}
return null;
}
}
然后你写
Factory f = building.adapt(Factory.class);
if (f != null)
f.printFactoryOutput();
还有更多的地方可以解决这个问题,但我认为这对于这个问题已经足够了。