繁体   English   中英

从Java中的父列表调用子方法

[英]Call child methods from parent list in Java

我有一个这样的设备父类

class Device{
    int id;
    public Device(int id);
}

和一些子设备

class SwitchDevice extends Device{
    boolean state;
    public SwitchDevice(int id);
    boolean getState();
    void setState(boolean state);
}

class LightDevice extends SwitchDevice{
    int value;
    public SwitchDevice(int id);
    int getValue();
    void setValue(int value);
 }

然后我有一个设备处理程序,它具有设备对象列表和一些从列表中检索设备实例的方法

class DeviceHandler {

    private List<Device> deviceList;

public DeviceHandler() {
        deviceList = new ArrayList<Device>();
}

public Device getById(int devId);
}

我想知道如何从该列表中调用childs方法,这意味着

Device dev = deviceHandler.getById(0);
boolean state = dev.getState;

我知道在Java中这是不可能的,但是也许您可以建议我如何实现结果。

我已经尝试过访问者模式,但是在我看来,这不是正确的模式,因为它不允许我返回值。

唯一的方法似乎是在处理程序类中为每个设备的每个值添加一个方法,如下所示

boolean getSwitchState(Device dev){
    if(dev.instanceOf(SwitchDevice)){
     SwitchDevice device = (SwitchDevice)dev;
     return device.getState();
    }else{
      throw new Exception();
}

但是它需要很多代码,并且不安全。

我希望您能理解我的意思(我的英语水平不是很好,并且不是Java程序员的专家)。

1.使用instanceof

您已经使用过instanceof,但是我不明白为什么在这里需要很多代码。 很安全

    Device dev = deviceHandler.getById(0);
    if (dev instanceof SwitchDevice) {

        ((SwitchDevice)dev).getState()
    }
    // More check instanceof

2.使用反射

    try {
        // Get public getState()
        Method m = dev.getClass().getMethod("getState");
        Boolean state = (Boolean )m.invoke(dev);

    } catch (NoSuchMethodException ex) {
       // dev is not SwitchDevice
    }

3.将所有常见行为添加到设备基类中(或接口?)

class Device{
    // ...
    public boolean getState() {
        throw new UnsupportedOperationException();
    }

    public int getValue() {
        throw new UnsupportedOperationException();
    }
}

class SwitchDevice extends Device {
    // ...

    @Override
    public boolean getState() {
        return this.state;
    }
}

class LightDevice extends SwitchDevice {
    // ...
    @Override
    public int getValue() {
        return this.value;
    }
}

对于此解决方案。 您需要注意UnsupportedOperationException

如果不可避免,至少要在一个地方进行铸造。 由于调用代码已经期望getById方法具有特定的子类,因此将该方法更新为泛型并在其中进行所有强制转换:

    public <T extends Device> Optional<T> getById(Class<T> deviceType, int devId){
        Device d = deviceList.get(devId);
        if ( d == null || !deviceType.isInstance(d) ) return Optional.empty();                        
        return Optional.of( deviceType.cast(d) );
    }

然后这样称呼它:

    Optional<SwitchDevice> sd = deviceHandler.getById(SwitchDevice.class, 1);        
    boolean state = sd.orElseThrow( () -> new Exception() ).getState();

或一支班轮:

    boolean state = deviceHandler.getById(SwitchDevice.class, 1)
                                 .orElseThrow( () -> new Exception() )
                                 .getState();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM