人们如何绕过需要不同数量的超类参数的子类init方法?

Iai*_*ain 3 c# java oop actionscript-3

想象一下,我有一个基本实体类的游戏,一个不带参数的init方法.现在我有一个Wizard类,但我希望传递2个参数,比如速度和强度.在AS3中(我相信Java和C#)我将不被允许这样做 - 它是一个"不兼容的覆盖",因为方法签名将不匹配.现在我可以改为创建一个"initWizard"方法,但后来我遇到了每个类的init方法可能有不同名称的问题.

我需要在AS3,Java或C#中工作的解决方案.

bac*_*dos 6

AS3不支持方法重载,但坦率地说,方法重载只是一种语法糖,通常只会引入歧义和不一致.

在Java中,一个方法由它的名称和它的签名决定,在AS3中,只有它的名字,但从语义上讲,它们之间的差别很小.

protected void init( int a )
protected void init( int a, int b )
Run Code Online (Sandbox Code Playgroud)

protected void init1( int a )
protected void init2( int a, int b )
Run Code Online (Sandbox Code Playgroud)

在AS3中,每个名称只能有一个方法,每个类只能有一个构造函数.但是,构造函数不需要具有兼容的签名.在AS3中你可以解决这个问题:

package {
 class A {
  private var a:int;
  public function A(a:int) {
   this.a = a;
  }
  // ... probably some meaningful methods here :)
 }
}
package {
 class B extends A {
  private var b:int;
  public function B(a:int, b:int) {
   super(a);
   this.b = b;
  }
  // ... probably some other meaningful methods here as well :D
 }
}
Run Code Online (Sandbox Code Playgroud)

您还可以避免ewernli提供的Java解决方案中的问题.

编辑:刚看到,你坚持不使用构造函数,而是使用不同签名的init方法.为什么?这违反了Liskov替代原则.

edit2: 我想你有两个选择:

  1. 初始化程序的不同名称(不是最好的想法,因为你的子类将公开初始化程序,只能部分工作(不好,参见上面提到的LSP)).
  2. 按照哲学生活,任何阶级都必须是抽象的或最终的.示例(假设太空游戏):

一个抽象基类,多个具体子类:

class ShipBase {//in Java you might wanna put the 'abstract' keyword just infront
 //... implementation of some sort
 //... maybe a protected intializer to call by subclasses
 //... no public initializer, since class is abstract
}
final class Fighter extends ShipBase {
 //... public initializer specific to Fighter
 //... other custom behaviour
}
final class Bomber extends ShipBase {
 //... I guess, this is obvious
}
Run Code Online (Sandbox Code Playgroud)

现在你可能会问自己:如果我想Fighter成为一个基类(比如说,那个EliteFighter2000),还有一个可实例化的类.简单.它不一定是.

class FighterBase extends ShipBase {
    //... implementation of whatever kind of things fighters have in common
    //... a protected intializer to call by subclasses    
}
final class Fighter extends FighterBase {
    //... public initializer possibly just forwarding to protected initializer
}
final class EliteFighter2000 extends FighterBase {
    //... here goes all the 'elite' stuff
}
Run Code Online (Sandbox Code Playgroud)

这也更灵活.您现在可以在Fighter不影响的情况下更改简单EliteFighter2000,或者您可以决定通过修改来改变所有战士的共同行为FighterBase.遗产通常是一件危险的事情,经常被误解和误用.
坚持这一规则通常有助于避免微妙但通常相当深远的耦合继承可能由于缺乏关注点而引入.在这种情况下,战斗机常见的任何东西都将被实施,FighterBase并且任何特定于简单的东西Fighters都在它所属的地方.

greetz
back2dos