Лучшая практика для вызова метода childclass из объекта parentclass - PullRequest
0 голосов
/ 23 октября 2019

Я знаю, этот вопрос звучит странно. Позвольте мне прояснить себя.


class Car ...

class Mercedes extends Car ...
class Porsche extends Car ... 




class Warehouse{
    Car car;
}


class WarehouseX extends Warehouse{
    public static void main(){
        ((Mercedes) super.car).doMercedesStuff();       
    }
}

Взгляните на этот вымышленный пример. Мерседес и Порше - это Автомобиль. Каждый склад имеет одну машину. Теперь у WarehouseX есть Mercedes. Однако WarehouseX наследует универсальный автомобиль от Warehouse. Как лучше всего назвать конкретные методы Mercedes на этом автомобиле. Одним из способов было бы привести его к Мерседесу, но мне это кажется безобразным. Есть ли лучший способ сделать это?

Ответы [ 4 ]

5 голосов
/ 23 октября 2019

Поскольку каждый склад должен владеть только одним конкретным типом автомобиля, можно использовать дженерики:

class Warehouse<T extends Car>{

    T car;
}

class WarehouseX extends Warehouse<Mercedes>{
    //do mercedes stuff
}

Теперь WarehouseX может обращаться к super.car и использовать его как Mercedes, поскольку наследование гарантирует его.

Редактировать: И поскольку люди говорят об абстрактных методах: Car должен реализовывать общие методы и объявлять абстрактный метод, если каждый конкретный автомобиль должен предоставить их. Если только подмножеству определенных автомобилей нужен метод, такой как openBackDoors (), следует объявить новый класс, расширяющий Car.

2 голосов
/ 23 октября 2019

Вы можете попробовать код ниже. Идея состоит не в том, чтобы создать несколько классов Warehouse для каждого автомобиля. Сделайте код немного универсальным и используйте команду инжектировать Car на складе во время создания объекта Warehouse

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();
    }
}
2 голосов
/ 23 октября 2019

Не следует создавать зависимость в этом направлении, суперкласс не может знать, что реализовано в подклассах.

Одним из решений является создание абстрактного метода в суперклассе

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

Для отслеживания ответа от Legacy, еслиВы делаете универсальный склад, который затем можете сделать

class WarehouseX extends Warehouse<Mercedes>{
    //...
    public void someMethod() {
        car.doModelSpecificStuff();
    }
}
0 голосов
/ 23 октября 2019

Подобные действия нарушают принципы обращения зависимостей (подробнее см. Принципы SOLID). Лучшая практика объясняется Иоакимом. Но вы можете попробовать это:

вместо:

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

 try this:  
 getCar().doModelSpecificStuff(); 

//in Warehouse class 
//getters   //not pivate
//setters
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...