2013-05-15 1 views
1

СценарийОбеспечить класс реализует по крайней мере, один метод

Ни в коем случае это реально, так возьмите пример с зерном соли. Это должно быть простым способом передать сценарий. С учетом сказанного, скажем, мы имеем следующие определения классов.

interface iVehicle { 
    public function getDescriptionFormat1(); 
    public function getDescriptionFormat2(); 
} 

class VehicleDescription { 
    ... 
} 

class TruckDescription extends VehicleDescription implements iVehicle { 
    ... 
} 

class CarDescription extends VehicleDescription implements iVehicle { 
    ... 
} 

Проблема

Классы CarDescription и TruckDescription может реализовать один или оба из описания форматов. Переопределение обоих методов в оба класса кажется неправильным, когда только один потребуется. Каков надлежащий способ реализации такого ограничения? Кроме того, вы можете попытаться продать меня на том, что это плохое дизайнерское решение.

Edit- я боюсь, что я был слишком расплывчатым с моим примером. Мои извинения. Два описания - это более или менее разные структуры данных, а не строки. Можно было бы возвращать массив, представляющий подробное описание 3 столбца в длину, а другой мог бы возвратить более основную таблицу описания с 2 столбцами

+0

В них можно использовать черты и абстрактные методы. Таким образом, Truck будет использовать truckTrait и должен будет реализовать только свои методы, и Car будет использовать только carTrait и должен будет реализовать свои методы. Но это тоже выглядит уродливо. –

+0

Извините, если я не был чист. Оба формата могут быть реализованы CarDescription и TruckDescription. – Kevin

+0

Ну, тогда почему бы просто не объявить их в «VehicleDescription» пустыми телами и реализовать при необходимости? –

ответ

2

Либо вы используете один метод для обоих и дать ему параметр для определения того, как он должен себя вести, например

interface iVehicle { 
    public function getDescription($Format); 
} 

class CarDescription extends VehicleDescription implements iVehicle { 
    public function getDescription($Format) { 
     switch ($Format) { 
      case 1: 
       // Do what needs to be done 
       break; 
      case 2: 
       // Do what needs to be done 
       break; 
      default: 
       throw new Exception('Error'); 
       break; 
    } 
} 

или использовать два интерфейса и класс реализует соответствующий интерфейс для него (или оба.)

interface iVehicle1 { 
    public function getDescriptionFormat1(); 
} 
interface iVehicle2 { 
    public function getDescriptionFormat2(); 
} 

// Let's skip forward 

class CarDescription extends VehicleDescription implements iVehicle1, iVehicle2 { 
    // ... 
} 

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

+0

Мне нравится второй пример. Это примерно так же близко к тому, что я ищу до сих пор. Я просто должен был бы проверить, что class_implements() один из трех разных интерфейсов. – Kevin

1

Возможно, вам следует использовать только один метод getDescriptionFormat() и предоставить соответствующие реализации для разных подклассов VehicleDescription класс.

EDIT

Я только что прочитал ваш комментарий на ваш вопрос, что классы могут реализовать оба метода. Если это то, что вы хотите, ваш пример уже в порядке. Единственное, что вы можете сделать, это предоставить пустые реализации в классе VehicleDescription.

касается того, как обеспечить, по крайней мере, один из методов реализуется в этом случае, я не думаю, что это возможно, но поправьте меня, если я ошибаюсь :)

1

Интерфейс можно рассматривать как договор. Любой класс, реализующий этот интерфейс, гарантирует, что он предоставит указанные функции.

Тем не менее, это полностью зависит от класса реализации, как он на самом деле это делает. В вашем примере TruckDescription и CarDescription может потребоваться вернуть различные форматы описания по различным причинам и таким образом реализовать getDescriptionFormat1() & getDescriptionFormat2() по-разному.

В основном это означает, что в интерфейсе вам, вероятно, потребуется только getDescriptionFormat(), а затем классы реализации могут реализовать эту функцию по мере необходимости.

Звучит так, как будто вы должны стандартизировать то, что возвращается. Возможно, класс формата, который может инкапсулировать описание? Я просто догадываюсь, так как я не знаю никаких подробностей, но я думаю, это то, что я буду рассматривать.

+0

Все очень верно, но, боюсь, я был слишком расплывчатым с моим примером. Мои извинения. Два описания - это более или менее разные форматы данных, а не строки. Можно было бы возвратить массив, представляющий подробное описание 3 столбца в длину, а другой мог бы вернуть более базовую таблицу описания с двумя столбцами. – Kevin

+1

Тогда, может быть, вы должны стандартизировать то, что возвращается? Возможно, класс формата, который может инкапсулировать описание? Я просто догадываюсь, так как я не знаю никаких подробностей, но я думаю, это то, что я буду рассматривать. – vascowhite

0

Вот как я мог бы заняться этим.

interface Describable { 
    public function getDescription(); 
} 

interface Sellable { 
    public function getPrice(); 
} 

// abstract class - can't create an instance but can hold shared methods and property definitions 
abstract class Vehicle implements Describable, Sellable { 
    abstract public function getDescription(); 

    // this can't be overloaded 
    final public function getPrice(){ 
     // code for get price 
    } 
    public function getColorOptions(){ 
     // this can be overloaded 
    } 
} 

// concrete class that just uses the abstracts' definitions 
class Car extends Vehicle { 
    public function getDescription(){ 
     // overload for cars 
    } 
} 

// concrete class that overloads one of the properties 
class Truck extends Vehicle { 
    public function getDescription(){ 
     // overload for trucks 
    } 
} 


class FlyingCar extends Car { 
    public function getDescription(){ 
     // Flying cars need a whole new description 
    } 

} 

В основном это шоу метод, который должен быть перегружен (getDescription в силу этого определяется как абстрактные)

тот, который не может быть перегружен (getPrice в силу этого определяется конечный)

и тот, который определен на абстракте, который можно либо перегрузить, либо использовать реализацию по умолчанию.