![]() |
|
||||||||||
|
|||||||
|
|
« Предыдущая тема | Следующая тема » |
| Опции темы | Опции просмотра |
|
![]() |
![]() |
|
|||||
|
Регистрация: Aug 2009
Сообщений: 19
|
Я хочу, чтобы некий класс A реализовывал интерфейс I и был Sprite.
У А будет много подклассов А1 А2 А3 (список расширяется), реализующих функции из I, при этом есть класс-манагер M, который эти A1 A2 ... создает в изобилии по требованию. Хотелось бы сделать поизящнее. Первое что напрашивается: - написать интерфейс I - A extends Sprite implements I - А1 extends A, А2 extends A, А3 extends A etc - манагер M имеет переменную типа A и создает одного из A1-A2-A3 в зависимости от вызова и рулит какое-то время Что не нравится: придется в A прописать пустые функци из I и в A1, A2, A3 постоянно override их, как-то не лежит душа. И вообще в этой схеме непонятно зачем нужен I, можно сразу прописать функции в A и override-ть их в А1 А2 А3, А в таком случае выполняет функцию абстрактного класса, для чего в AS3 интерфейсы и есть. Если не писать интерфейс I и A, а напрямую делать A1 A2 A3, то это вообще паршиво - если программер делающий A4 A5 пропустит нужные функции, будет плохо. Если не делать A, а напрямую реализовывать I в А1 А2 А3 А1 extends Sprite implements I А2 extends Sprite implements I то не совсем понятно, как проверить в M соответствие типа, если переменная для экземпляра будет типа Sprite, то нет гарантии, что в A5 реализовали I, если же переменная будет типа I, то для оперирования с этой переменной как со Sprite придется постоянно приводить тип, что тоже неизяЩно Как бы тут поступить поООПшней? |
|
|||||
|
Регистрация: Aug 2009
Сообщений: 19
|
Это понятно, это контроль при создании и throw error, мне просто лениво постоянно делать override и приводить тип
Вот я и ищу более кузявый путь, чтобы "сразу и само". Если вариантов нет, буду так как выше делать. |
|
|||||
|
Регистрация: Jan 2009
Сообщений: 1,651
|
|
|
|||||
|
Регистрация: Aug 2009
Сообщений: 19
|
Вово, тыща временных foo
И вечные override method1, override method2 в A1 A2 не нравятся. И контроля типа на уровне компиляции нет. И интерфейс I в таком случае просто не нужен ни в каком разрезе. Вот есть способ сделать сразу и все? Если нет, я смирюсь ![]() Вот если б в интерфейсе можно было бы писать, что его имплементоры обязаны наследовать от Sprite вот это было бы оно, как мне кажется. Последний раз редактировалось SorrowN00b; 14.08.2009 в 16:00. |
|
|||||
|
.
|
Вариант первый: Вам придется оверрайдить методы в подклассах, расширяющих A и не использовать интерфейс I вовсе. Следить за тем, чтобы методы были заоверрайдены придется вручную. На этапе компиляции это не удастся отследить. Инстансы A1, A2...AN будут иметь тип A. A extends Sprite А1 extends A А2 extends A А3 extends A class A extends Sprite {
public virtual function doSomething():void {
throw new IllegalOperationError('Method must be overrided by subclass');
}
}
А1 extends A {
public override function doSomething():void {
trace('Hello, I am А1');
}
}
А2 extends A {
public override function doSomething():void {
trace('Hello, I am А2');
}
}
class M {
public function M() {
this.doJob();
}
public function doJob():void {
var className:String = 'A' + int(Math.random() * 2) + 1;
var c:Class = getDefinitionByName(className) as Class;
var instance:A = new c() as A;
instance.x = 100;
instance.doSomethimg();
}
}
Интерфейсы позволяют единообразно оперировать с экземплярами совершенно разных типов, не имеющих в иерархии их классов общего суперкласса. При этом экземпляр приобретает тип интерфейса. Для этого варианта в I должны быть описаны _все_ геттеры/сеттеры и методы, через которые предполагается работать с экземпляром. Опишите в I все проперти и методы Sprite с которыми собираетесь работать, а также методы и проперти, реализуемые во всех A1, A2...AN. Для code reusing полезно отекстендить I от ISprite. А1 extends Sprite implements I А2 extends Sprite implements I А3 extends Sprite implements I А1 extends Sprite implements I {
public function doSomething():void {
trace('Hello, I am А1');
}
}
А2 extends Sprite implements I {
public function doSomething():void {
trace('Hello, I am А2');
}
}
public interface ISprite {
// DisplayObject implementation
function set x(value:Number):void;
function get x():Number;
}
public interface I extends ISprite {
function doSomething():void;
}
class M {
public function M() {
this._factory = new AFactory();
this.doJob();
}
private var _factory: IIFactory;
public function doJob():void {
var className:String = 'A' + int(Math.random() * 2) + 1;
var instance:I = this._factory.newInstance(className);
if (instance != null) {
instance.x = 100;
instance.doSomethimg();
}
}
}
internal class AFactory implements IIFactory {
public function newInstance(className:String):I {
try {
var c:Class = getDefinitionByName(className) as Class;
var instance:I = new c() as I;
return instance;
} catch (e:TypeError) {
return null;
}
}
}
|
|
|||||
|
Регистрация: Aug 2009
Сообщений: 19
|
Ну, это все понятно, не стоило утруждаться так все подробно расписывать, спасибо за ваше время
![]() Во втором варианте, конечно, напрягает следующее: Цитата:
|
![]() |
![]() |
Часовой пояс GMT +4, время: 03:29. |
|
|
« Предыдущая тема | Следующая тема » |
|
|