Этот вопрос предназначен для применения к интерфейсам в целом, но я буду использовать AS3 / Flex для моего языка. Должно быть [в основном] очевидно, как применять его на разных языках.
Если я создаю базовый класс, и он расширяет интерфейс, то будет определен явный контракт: для каждого метода в интерфейсе базовый класс должен реализовать указанный метод.
Это достаточно просто. Но я не понимаю, почему у вас есть возможность привести интерфейсный экземпляр обратно в исходный базовый класс. Конечно, мне приходилось делать это несколько раз (пример ниже очень близок к ситуации, с которой я борюсь), но это не значит, что я понимаю: ^)
Вот пример интерфейса:
public interface IFooable extends IUIComponent {
function runFoo():void;
}
Допустим, я создаю базовый класс, который расширяет VBox и реализует интерфейс:
public class Foo extends VBox implements IFooable {
public Foo() {
super();
//stuff here to create Foo..blah blah
}
public function runFoo():void {
// do something to run foo
}
}
Теперь я использовал интерфейс потому, что хочу гарантировать, что runFoo всегда реализован. Это общая часть функциональности, которую должны иметь все мои классы, независимо от того, как они их реализуют. Таким образом, мой родительский класс (Приложение) будет создавать экземпляр Foo через его интерфейс:
public function init():void {
var foo:IFooable = new Foo();
foo.percentHeight = 100; //works because of IUIComponent
}
Но , если я хочу добавить Foo в контейнер приложения, мне теперь нужно привести его обратно к базовому классу (или к другому базовому классу):
public function init():void {
var foo:IFooable = new Foo();
foo.percentHeight = 100;
addChild(foo as DisplayObject); //_have_ to cast, because addChild takes a 'DisplayObject' class type
//could also do this:
//addChild(foo as VBox);
}
Не было ли первоначальное намерение скрывать реализацию Foo? Существует предположение, что Foo является объектом DisplayObject. К сожалению, возможность добавить пользовательский объект в контейнер кажется невозможной без приведения.
Я что-то упустил полностью? Это действительно просто феномен в Flex / AS3? Если у вас есть контейнер в базовом API языка, и он позволяет вам только добавлять дочерние элементы определенного типа класса, как вы тогда абстрагируете реализацию?
Для записи, этот вопрос , кажется, задает вопрос, возможна ли такая операция , возможна , но на самом деле не рассматривается, почему это может быть плохой дизайн (и как исправить это).
2-я мысль:
Абстрактные классы :
Как указал Мэтью, абстрактные классы помогают решить некоторые из этих задач: я мог бы создать базовый абстрактный класс, который наследуется от DisplayObject (или, в моем случае, VBox, поскольку он является дочерним по отношению к DisplayObject), и иметь Базовый класс реализует интерфейс. Таким образом, любой класс, который расширяет абстрактный класс, будет тогда необходим для реализации в нем методов.
Отличная идея - но AS3 не имеет абстрактных классов (насколько я знаю).
Итак, я мог бы создать базовый класс, который реализует интерфейс и расширяет VBox, и наследуется от него, и я мог бы вставить код в те методы, которые необходимо расширить; такой код выдаст ошибку, если базовый класс является исполнителем. К сожалению, это проверка во время выполнения, а не принудительное выполнение во время компиляции.
Это все же решение.
Контекст
Некоторый контекст может помочь:
У меня есть приложение, которое может иметь любое количество субконтейнеров. Каждый из этих субконтейнеров будет иметь свои собственные соответствующие параметры конфигурации, параметры и т. Д. Однако само приложение имеет глобальный ApplicationControlBar, который будет содержать меню точки входа для доступа к этим параметрам конфигурации. Поэтому всякий раз, когда я добавляю подкомпонент в основное приложение (через «addChild»), он также «регистрирует» свои собственные параметры конфигурации в меню ApplicationControlBar. Это сохраняет знания о конфигурируемости самих контейнеров, но позволяет использовать более унифицированные средства доступа к ним.
Таким образом, когда я создаю каждый контейнер, я хочу создать их экземпляр через их интерфейс, чтобы я мог гарантировать, что они могут зарегистрироваться в ApplicationControlBar. Но когда я добавляю их в приложение, они должны быть базовым классом.