Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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 从parentclass对象调用childclass方法的最佳实践_Java_Oop_Inheritance_Casting - Fatal编程技术网

Java 从parentclass对象调用childclass方法的最佳实践

Java 从parentclass对象调用childclass方法的最佳实践,java,oop,inheritance,casting,Java,Oop,Inheritance,Casting,我知道这个问题听起来令人困惑。让我澄清一下 班车。。。 奔驰级轿车。。。 类保时捷扩展车。。。 类仓库{ 汽车; } 类WarehouseX扩展了仓库{ 公共静态真空总管{ 梅赛德斯超级轿车; } } 看看这个虚构的例子。梅赛德斯和保时捷是一辆汽车。每个仓库都有一辆车。 现在,WarehouseX有一辆奔驰。然而,WarehouseX从Warehouse继承了一辆通用汽车。 在这辆车上调用特定梅赛德斯方法的最佳方式是什么。一种方法是把它扔给奔驰,但我觉得这很难看。有更好的方法来实现这一点吗?您不

我知道这个问题听起来令人困惑。让我澄清一下

班车。。。 奔驰级轿车。。。 类保时捷扩展车。。。 类仓库{ 汽车; } 类WarehouseX扩展了仓库{ 公共静态真空总管{ 梅赛德斯超级轿车; } } 看看这个虚构的例子。梅赛德斯和保时捷是一辆汽车。每个仓库都有一辆车。 现在,WarehouseX有一辆奔驰。然而,WarehouseX从Warehouse继承了一辆通用汽车。
在这辆车上调用特定梅赛德斯方法的最佳方式是什么。一种方法是把它扔给奔驰,但我觉得这很难看。有更好的方法来实现这一点吗?

您不应该在这个方向上创建依赖项,超类无法知道子类实现了什么

一种解决方案是在超类中创建一个抽象方法

//Car class
public abstract void doModelSpecificStuff();
然后在你汽车课上的某个地方叫它。然后,每个子类实现这个方法,并执行特定于该车型的操作

//Mercedes class
@Override
public void doModelSpecificStuff() {
    doMercedesStuff();
}
仓库代码将是

class WarehouseX extends Warehouse{
    public static void main(){
        Warehouse warehouse = new WarehouseX();
        warehouse.car.doModelSpecificStuff(); 
    }      
}
为了跟进遗留问题的答案,如果您将仓库设置为通用的,那么您可以这样做

class WarehouseX extends Warehouse<Mercedes>{
    //...
    public void someMethod() {
        car.doModelSpecificStuff();
    }
}

由于每个仓库只应拥有一种特定的汽车类型,因此可以使用泛型:

class Warehouse<T extends Car>{

    T car;
}

class WarehouseX extends Warehouse<Mercedes>{
    //do mercedes stuff
}
WarehouseX现在可以访问super.car并将其用作Mercedes,因为继承 保证它


编辑:既然人们在谈论抽象方法:Car应该实现通用方法并声明抽象方法,如果每个特定的Car需要提供它们的话。如果只有特定car的一个子集需要一个方法,比如openBackDoors,那么应该声明一个新的类扩展car。

这样做违反了依赖倒置原则。有关详细信息,请参阅实体原则。 Joakim解释了最佳实践。 但你可以试试这个:

而不是:

 Warehouse warehouse = new WarehouseX();
 warehouse.car.doModelSpecificStuff(); 

 try this:  
 getCar().doModelSpecificStuff(); 

//in Warehouse class 
//getters   //not pivate
//setters

您可以尝试下面的代码。 我们的想法不是为每辆车创建多个仓库类别。 将代码位设为泛型,并在创建仓库对象时在仓库中使用InjectCar

abstract class Car{
    public abstract void doCarStuff();
}
class Mercedes extends Car{
    @Override
    public void doCarStuff() {
        System.out.println("Mercedes stuff");
    }
}
class Ferrari extends Car{
    @Override
    public void doCarStuff() {
        System.out.println("Ferrari stuff");
    }
}
class Warehouse{
    private Car car;
    public Warehouse(Car car) {
        this.car = car;
    }
    public Car getCar() {
        return car;
    }
}
public class TestCarWarehouse {
    public static void main(String[] args) {
        Warehouse warehouseX = new Warehouse(new Mercedes());
        warehouseX.getCar().doCarStuff();
        Warehouse warehouseY = new Warehouse(new Ferrari());
        warehouseY.getCar().doCarStuff();
    }
}

你可以给Car一个方法doBrandSpecificStuff,在Mercedes和Porsche中通过调用真正的方法来覆盖它,比如@override public void doBrandSpecificStuff{doMercedesStuff;}。也有点难看,但我更喜欢它而不是铸造实例。。。顺便说一句,汽车可以是一个界面,不是吗?你在找一个通用的汽车容器吗?或者你需要对仓库做什么?是的,这是可行的,但这意味着你需要一个超级方法来处理每一个方法。此外,如果说梅赛德斯有一个方法自动更正,而保时捷没有这种能力,那么我们如何证明这一点呢?混合了静态/实例的代码片段不起作用,应该更改。问题中的代码不清楚,在没有初始化的情况下从main调用一个实例,所以我选择了一条捷径,可能是简略的:由于通用WarehouseX确实知道它拥有一辆Mercedes,因此知道Mercedes方法。WarehouseX是仓库的具体化,因此不是通用的,但仍然在WarehouseX中,这辆车是梅赛德斯型的。这是因为我们这么说,T必须是一个具体的类,它从Car扩展而来,因此增加了更多information@JoakimDanielson这不是泛型的重点。当然,在使用之后,汽车实例不再是普通汽车了。是的,我的大脑放屁了。我删除我的评论。我在考虑使用像Warehouse w=new WarehouseX这样的泛型;