向下转换对象到接口

时间:2016-06-14 12:22:30

标签: java inheritance subclass superclass implements

简而言之,我希望能够通过不实现某个接口的超类对类实例进行分组。但是从一组实例中,我想在实现该接口的那些实例上从接口调用方法。

可能解释它的一些示例代码。

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'超级国旗。

感谢。

2 个答案:

答案 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

这有一个问题,即BuildingFactory之间目前没有必要的关系,但这种关系可能对您有帮助。

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();

还有更多的地方可以解决这个问题,但我认为这对于这个问题已经足够了。