从Java

时间:2018-02-22 16:31:44

标签: java list downcast

我有像这样的设备父类

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

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

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中这是不可能的,但也许你可以建议我如何实现de result。

我尝试了访问者模式,但在我的情况下不是正确的,因为它不允许我返回值。

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

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

但它需要大量代码并且不安全。

我希望你明白我的意思(我的英语不是很好,而不是专业的java程序员)。

2 个答案:

答案 0 :(得分:1)

<强> 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。将所有常见行为添加到设备基类(OR接口?)

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

答案 1 :(得分:0)

如果处理铸造是不可避免的,至少在一个地方进行。由于调用代码已经预期来自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();