2013-09-16 2 views
2

Это мое абстрактное AbstractVehicles класса, который реализует интерфейс транспортных средствМогу ли я передать объект из подкласса в абстрактный класс?

public abstract class AbstractVehicles implements Vehicles{ 

} 

и вот моего CarImpl

public class CarImpl extends AbstractVehicles implements Car { 
    private CarAI ai; 
    private static final int CAR_FUEL_LEFT = 10; 
    public CarImpl(){ 
     super(FUEL_LEFT); 
     this.ai = new CarAI(); 
    }   
    public void move(World w){ 
     // AI is using here 
     ai.act(w); 
    } 
} 

и вот мой BicycleImpl

public class BicycleImpl extends AbstractVehicles implements Bicycle { 
    private BicycleAI ai; 
    private static final int BICYCLE_FUEL_LEFT = 10; 
    public BicycleImpl(){ 
     super(BICYCLE_FUEL_LEFT); 
     this.ai = new BicycleAI(); 
    }   
    public void move(World w){ 
     // AI is using here 
     ai.act(w); 
    } 
} 

где интерфейс автомобилей и велосипедов является маркер интерфейс что

public interface Car extends Vehicles { 
} 


public interface Bicycle extends Vehicles { 
} 

Вопрос пришел сюда Я внедрил AI для автомобилей и велосипедов отдельно в других упаковках под названием BicycleAI и CarAI. Но код в их CarImpl и BicycleImpl одинаковый. Поэтому я хотел бы добавить это в абстрактный класс, чтобы код можно было повторно использовать. И класс BicycleAI и класс CarAI реализует интерфейс AI.

Как мы видим выше, их код для действия тот же, но там объекты ИИ различны. В любом случае я могу поместить этот код в абстрактный класс?

Я пытался сделать это

public abstract class AbstractVehicles implements Vehicles{ 
    protected AI ai; 
    private int fuelLeft; 
    public AbstractVehicles(int fuelLeft){ 
     this.fuleLeft = fuelLeft 
     AI ai = new AI(); 
    } 
    public void move(World w){ 
     ai.act(w); // But I have no idea this is CarAI or BicycleAI 
    } 
} 

Я немного запутался о конструкторе в AbstractVehicles и конструктор в RabbitImpl. Если я создаю объект RabbitImpl, и я вызываю ход.

+0

На самом деле вы можете просто поместить движение в AbstractVehicles. Абстрактные классы могут иметь конкретные методы. – Cruncher

+2

Итак, что случилось с тем, что вы пробовали? –

+0

Является ли ваш 'CarAI' или' BicycleAI' подклассом 'AI'? –

ответ

1

Вы можете использовать Template Method в шаблон, в котором супер класс откладывает определенные шаги для его подкомитетов классов посредством использования абстрактных методов. Шаг, который вы должны делегировать своим дочерним классам здесь, - это предоставить фактическую реализацию AI, которая будет использоваться остальной частью родительского abstract код класса, который вы хотите, чтобы дочерние классы делились.

public abstract class AbstractVehicles implements Vehicles{ 
    protected AI ai; 

    public AbstractVehicles(){ 
     AI ai = initAI(); 
    } 

    protected abstract AI initAI(); // template method 

    public void move(World w){ 
     ai.act(w); // But I have no idea this is CarAI or BicycleAI 
    } 
} 

Теперь ваши Car и Bicycle классы будут обеспечивать реализацию шаблона в качестве

public class CarImpl extends AbstractVehicles implements Car { 

    protected AI initAI() { 
     return new CarAI(); 
    } 
} 

public class BicycleImpl extends AbstractVehicles implements Car { 

    protected AI initAI() { 
     return new BicycleAI(); 
    } 
} 
+0

Большое вам спасибо! –

+0

Собственно, это считается ОЧЕНЬ ПЛОХОЙ практикой. НИКОГДА не следует вызывать неконтактный метод из конструктора. Это еще хуже, если метод называется абстрактным. Это связано с тем, что метод вызывается в классе, конструктор которого не завершен. Если метод переопределения зависит от любых полей, инициализированных в конструкторе, это, скорее всего, не удастся. –

+0

@JohnB, единственная цель переопределения - предоставить экземпляр здесь. Он не зависит от того, в каком состоянии находится объект. –

0

this относится к конкретному классу. Таким образом, this.ai или ai является ссылкой на фактическое поле класса реализации.

2

Пропустите AI к абстрактному классу конструктор.

public abstract class AbstractVehicles implements Vehicles{ 
    protected final AI ai; 
    public AbstractVehicles(AI ai){ 
     this.ai = ai; 
    } 
    public void move(World w){ 
    ai.act(w); 
    } 
} 

public class CarImpl extends AbstractVehicles implements Car { 
    public CarImpl(){ 
     super(new CarAI()); 
    } 
} 
+0

Большое вам спасибо. Но когда я это делаю, они нуждаются в моем ai в AbstractVehicles, который сначала возвращается в CarAI? –

+0

Ох .. Я исправил это. –

+0

В будущем, пожалуйста, не редактируйте ответ, чтобы задать вопрос об этом. –

1

Вы можете использовать шаблоны в дополнение к Абстрактный ИИ, чтобы сделать его знать специфику

public abstract class AbstractVehicles<AI extends AbstractAI> implements Vehicles { 
    protected AI ai; 

    public AbstractVehicles(AI ai){ 
     this.ai = ai; 
    } 

    public void move(World w){ 
     ai.move(w); 
    } 
} 

Конечно недостаток этой конструкции вы не можете точно взять общий класс и построить это в вашем абстрактном классе.Однако вы можете сделать это очень хорошо для суб классов

public abstract class CarImpl extends AbstractVehicles<CarAI> implements Car{ 

    public CarImpl(){ 
     super(new CarAI()); 
    } 
} 

Делая это, все ссылки AI в пределах CarImpl будет определять, как CarAI благодаря родовым печатать.

Смежные вопросы