Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在运行时强制转换正确的子类_Java_Abstract Class - Fatal编程技术网

Java 在运行时强制转换正确的子类

Java 在运行时强制转换正确的子类,java,abstract-class,Java,Abstract Class,我有以下基类和派生类: public abstract class Drone { public void Drone(){} public abstract boolean commonFunc(); } public class DroneMain extends Drone { @Override public boolean commonFunc(){ return false; } public boolean dro

我有以下基类和派生类:

public abstract class Drone {
    public void Drone(){}
    public abstract boolean commonFunc();
}

public class DroneMain extends Drone {
    @Override
    public boolean commonFunc(){
        return false;
    }

    public boolean droneMainFunc(){
        return true;
    }
}

public class DroneOther extends Drone {
    @Override
    public boolean commonFunc(){
        return true;
    }

    public boolean droneOtherFunc(){
        return false;
    }
}

public class DroneMgr {
    public enum DroneType {MAIN, OTHER}

    public Drone getDrone(DroneType type){
        if (type.equals(DroneType.MAIN))
            return new DroneMain();
        else
            return new DroneOther();
    }
}
调用这些类的代码如下所示:

private DroneManager droneManager;
private Drone drone;

droneManager = new DroneManager();
drone = droneManager.getDrone(DroneManager.DroneType.MAIN);
boolean value = drone.droneMainFunc();
我的问题是关于以下几行:

drone = droneManager.getDrone(DroneManager.DroneType.MAIN);
boolean value = drone.droneMainFunc();
如何使其能够从无人机对象调用drone mainfunc()

否则,如果我直到运行时才知道它的类型,我该如何做呢。
如果我不能使用Drone(Drone实例),那么直到运行时我才知道,我必须创建一个Drone主对象和一个Drone其他对象,然后根据返回的类型仅分配/强制转换一个。我希望避免这种情况,因为我确信有一种更好的模式。

最简单的方法是使用
instanceof
操作符

drone = droneManager.getDrone(DroneManager.DroneType.MAIN);
if (drone instanceof DroneMain) {
    ((DroneMain)drone).droneMainFunc();
} ...
<>但是我想把另一种抽象方法加入到你的代码>无人机< /Cux>类中,它只需调用正确的函数即可。这是因为您似乎想要在它的实际类上独立执行一个函数。如果是这样,您应该在抽象类中包含另一个公共函数,这两个实现都可以使用,就像您的
Drone\commonFunc

public abstract class Drone {
   public void Drone(){}
   public abstract boolean commonFunc();
   public abstract boolean doSomething();
}

public class DroneMain extends Drone {
   @Override
   public boolean commonFunc(){
       return false;
   }

   @Override
   public boolean doSomething() {
       return droneMainFunc();
   }

   public boolean droneMainFunc(){
       return true;
   }
}

public class DroneOther extends Drone {
   @Override
   public boolean commonFunc(){
       return true;
   }

   @Override
   public boolean doSomething() {
       return droneOtherFunc();
   }

   public boolean droneOtherFunc(){
       return false;
   }
}

...

boolean value = drone.doSomething();

我给你两个选择:

跳过枚举,改用类和泛型。这允许您在DroneMgr中对类型进行断言,并将正确的断言作为正确的类型返回

public class DroneMgr {
    public <T extends Drone> T getDrone(Class<T> type) {
        if(DroneMain.class.equals(type)) {
            // Need to cast to T, but we already know that T is DroneMain
            return (T) new DroneMain();
        } else if (DroneOther.class.equals(type)) {
            return (T) new DroneOther();
        } else {
            throw new IllegalArgumentException("Unknown Drone class " + type);
        }
    }
}
另一种选择是使用策略模式并直接在枚举中实现功能,这使得添加新类型变得容易

public enum DroneType {
    MAIN {
        @Override
        public boolean handle() {
            return new DroneMain().droneMainFunc();
        }
    },
    OTHER {
        @Override
        public boolean handle() {
            return new DroneMain().droneOtherFunc();
        }
    };

    public abstract boolean handle();
}
那么你只要做:

boolean value = DroneType.MAIN.handle();
如果您不喜欢在枚举中编写实现,那么可以将功能分解为单独的类,这些类都实现了一个公共接口,并且只引用枚举中的实例

public interface DroneHandler {
    boolean handle();
}

public class DroneMainHandler implements DroneHandler {
    @Override
    public boolean handle() {
        return new DroneMain().droneMainFunc();
    }
}

public class DroneOtherHandler implements DroneHandler {
    @Override
    public boolean handle() {
        return new DroneOther().droneMainFunc();
    }
}

public enum DroneType {
    MAIN(new DroneMainHandler()),
    OTHER(new DroneOtherHandler());

    public final DroneHandler handler;

    private DroneType(final DroneHandler handler) {
        this.handler = handler;
    }
}
然后,用法变为:

boolean value = DroneType.MAIN.handler.handle();

尽管如此,
publicGetDrone
需要返回类型。另外,通过调用
DroneManager.DroneType.MAIN
您应该知道它确实返回了
DroneMain
,并且您应该能够在之后强制转换它。@KevinEsche-这意味着我必须声明这两种类型,然后只实例化一种,而将另一种保留为空?添加了一个返回值Drone,thx。谢谢@Raniz。基于您使用泛型的第一个解决方案,它使我在某种程度上改变了我的问题。这让我意识到,我希望能够保留drone实例,并使用它来调用仅在drone main中定义的方法。所以,确切地说,我是这样理解的:'drone=droneManager.getDrone(droneManager.DroneType.MAIN);布尔值=drone.droneMainFunc();'
boolean value = DroneType.MAIN.handler.handle();