ООП вопрос о наилучшем способе ссылки на защищенную переменную базового класса без необходимости типизировать каждый раз, когда она используется - PullRequest
0 голосов
/ 25 августа 2011

У меня быстрый вопрос ООП, и я хотел бы посмотреть, как другие подойдут к этой конкретной ситуации. Вот оно:

Класс A (базовый класс) -> Класс B (расширяет класс A) Класс C (базовый класс) -> Класс D (расширяет класс C)

Все так просто, верно? Теперь класс A может получить экземпляр класса C через его конструктор. Аналогично, класс B может получить экземпляр класса C или класса D через свой конструктор. Вот небольшой фрагмент кода:

Class A
{
    protected var _data:C;
    public function A( data:C )
    {
        _data = data;
    }
}

Class B extends A
{
    public function B( data:D )
    {
        super( data );
    }
}

Class C
{
    public var someVar:String; // Using public for example so I don't need to write an mutator or accessor
    public function C() { } // empty constructor for example
}

Class D extends C
{
    public var someVar2:String; // Using public for example so I don't need to write an mutator or accessor
    public function D() { super(); } // empty constructor for example
}

Итак, допустим, что я использую класс B. Поскольку _data была определена как защищенная переменная в классе A как тип C, мне нужно будет каждый раз вводить переменную _data для типа D в классе B каждый раз, когда я хочу ее использовать. , Я действительно хотел бы избежать этого, если это возможно. Я уверен, что есть образец для этого, но не знаю, что это. Сейчас я решаю проблему, выполнив следующие действия:

Class B extends A
{
    private var _data2:D;
    public function B( data:D )
    {
        super( data );
        _data2 = data;
    }
}

Теперь в классе B я могу использовать _data2 вместо типизации _data для ввода D каждый раз, когда я хочу его использовать. Я думаю, что может быть более чистое решение, которое использовали другие. Мысли?

Ответы [ 2 ]

0 голосов
/ 30 декабря 2011

Большинство современных языков OO поддерживают ковариант возвращаемого типа, то есть переопределенный метод может иметь возвращаемый тип, который является подклассом возвращаемого типа в исходном (переопределенном) методе.

Таким образом, хитрость заключается в том, чтобы определить метод-получатель в A, который будет возвращать C, а затем B переопределить его, чтобы он возвращал D. Для этого переменная _data является неизменной: она инициализируется во время построенияи с этого момента он не меняет своего значения.

Class A {
  private var _data:C;
  public function A(data:C) {
    _data = data;
  }

  public function getData() : C {
    return _data;
  }

  // No function that takes a C value and assigns it to _data!      
}

Class B extends A  {
  public function B(data:D) {
    super(data);
  }  

  public function getData() : D { // Override and change return type
    return (D) super.getData();   // Downcast only once.
  }
}

Так я обычно пишу на Java:

public class A {
  private final C data;

  public A(C data) { this.data = data; }
  public C getData() { return data; }
}

public class B extends A {
  public B(D data) { super(data); }
  @Override
  public D getData() { return (D) super.getData(); }
}
0 голосов
/ 30 декабря 2011

Я думаю, что B не принимает C или D ... для того, чтобы он делал то, что вы написали, он должен быть

public function B( data:C )
{
    super( data );
}

По крайней мере, насколько я знал :) Я сомневаюсь, что вы можете использовать наследуемое наследство в вашем случае.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...