所以我有两个子类,它们在 Flex 中扩展了不同的基类,我怎样才能将它们组合起来,这样我就不会重复自己了。
基本上我有类似的东西
public class A extends B {
// methods
}
public class C extends D {
// same methods as class A
}
任何组合方式,这样我就不会重复相同的代码两次。
所以我有两个子类,它们在 Flex 中扩展了不同的基类,我怎样才能将它们组合起来,这样我就不会重复自己了。
基本上我有类似的东西
public class A extends B {
// methods
}
public class C extends D {
// same methods as class A
}
任何组合方式,这样我就不会重复相同的代码两次。
所以,问题是,你应该如何组合解决方案?
一种可能性是使用装饰器模式。这本质上是您现有类的包装器。为了完成这项工作,您的类可能需要实现一个接口,该接口公开您完成这项工作所需的一切。
所以像:
public interface IFoo {
function get name():String;
function set name(value:String):void;
}
public class A extends B implements IFoo {
protected var _name:String;
public function get name():String {
return _name;
}
public function set name(value:String):void {
_name = value;
}
}
public class C extends D implements IFoo {
protected var _name:String;
public function get name():String {
return _name;
}
public function set name(value:String):void {
if (_value != _name) {
_name = value;
dispatchEvent(new Event('nameChanged'));
}
}
}
public class FooDecorator {
protected var _foo:IFoo;
public function FooDecorator(foo:IFoo) {
_foo = foo;
}
public function sayName():void {
trace('foo name is', _foo.name);
}
}
另一种解决方案是给 A 和 C 封装行为的第五种类型的成员变量(就像 Jeffry 所说的那样,但我更愿意在可能的情况下遵守Demeter 定律):
class NameSayer {
function sayName(name:String):void {
trace('foo name is', _foo.name);
}
}
然后
public class A extends B {
public var name:String;
public var sayer:NameSayer;
//note that this method would be identical in both Classes
//but this is OK because the underlying logic is encapsulated
//and can be easily changed
public function sayName():void {
if (sayer) {
sayer.sayName();
}
}
}
我认为许多开发人员过于热衷于遵循 DRY,正如 Jeffry 所说,这可能会导致您的架构中出现其他更糟糕的问题。如果有的话,这些解决方案中的哪一个是合适的将取决于您要完成的工作。
您有两个实现完全相同方法的子类(扩展不同的父类)。
public class B {}
public class D {}
public class A extends B {
// methods
m1();
m2();
...
}
public class C extends D {
// same methods as class A
m1();
m2();
...
}
现在让我们提出一些观点。
现在,在您的情况下,您有 m1(), m2(), ... 方法出现在两个不同的类中。这增加了它们可能与这些类的状态没有真正联系的可能性。如果是这样,那么更好的解决方案是将它们完全删除到一个新类中。
如果你这样做,
--
//Parent classes (child classes are now gone)
public class B {}
public class D {}
--
// Your new class
public class X {
// methods that previously were in A and C
m1();
m2();
...
}
虽然,我对它的使用感觉很复杂;您可以使用包含指令。
创建一个文件,像这样,命名为 sharedMethods.as (或任何你想要的)。这不是真正的课程;它只包含代码片段:
public var mySharedMethod(mySharedMethodArguments:ArgumentType):void{
// do something
}
然后你可以将它包含在你的其他课程中:
public class A extends B {
include "sharedMethods.as";
}
public class C extends D {
include "sharedMethods.as";
}
包含文件中的代码将作为 A 类和 C 类的一部分进行编译。
您还可以将您的共享代码放在另一个类中,并在 A 和 C 中都有该类的实例。然后您必须编写包装器方法或向下钻取调用,如下所示:aInstance.sharedCodeObject.sharedMethod();
我的直觉是,如果您经常遇到这种情况;您可能对需要重构的对象模型有问题。