0

所以我有两个子类,它们在 Flex 中扩展了不同的基类,我怎样才能将它们组合起来,这样我就不会重复自己了。

基本上我有类似的东西

public class A extends B {
 // methods
}

public class C extends D {
 // same methods as class A
}

任何组合方式,这样我就不会重复相同的代码两次。

4

3 回答 3

1

优先组合而不是继承

所以,问题是,你应该如何组合解决方案?

一种可能性是使用装饰器模式。这本质上是您现有类的包装器。为了完成这项工作,您的类可能需要实现一个接口,该接口公开您完成这项工作所需的一切。

所以像:

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 所说,这可能会导致您的架构中出现其他更糟糕的问题。如果有的话,这些解决方案中的哪一个是合适的将取决于您要完成的工作。

于 2013-02-08T06:08:30.823 回答
1

您有两个实现完全相同方法的子类(扩展不同的父类)。

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();
 ...
}

现在让我们提出一些观点。

  • 在将方法分配给类时,基本思想是,该方法或行为确实属于该类 - 它实际上是该类或类型的属性。例如,Animal 的呼吸。在这种情况下,行为与类状态(或数据、属性或变量)相关联。如果一个方法不以任何方式访问类变量,那么该方法可能不属于那里。至少这是一般规则。

现在,在您的情况下,您有 m1(), m2(), ... 方法出现在两个不同的类中。这增加了它们可能与这些类的状态没有真正联系的可能性。如果是这样,那么更好的解决方案是将它们完全删除到一个新类中。

如果你这样做,

  1. 您还将摆脱现在仅为此目的而存在的两个类 A 和 C。
  2. 你摆脱了两个继承关系。这使您的代码更简单。
  3. 而且,您将实现不重复自己的目标。

--

//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();
 ...
}
于 2013-02-08T15:19:17.113 回答
0

虽然,我对它的使用感觉很复杂;您可以使用包含指令。

创建一个文件,像这样,命名为 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();

我的直觉是,如果您经常遇到这种情况;您可能对需要重构的对象模型有问题。

于 2013-02-07T18:24:51.063 回答