我有一个关于如何用不允许多重继承的语言处理以下场景的理论问题。
想象一下,我有一个基类 Foo ,我想从中创建三个子类:
想象一下,实现功能“A”和“B”的代码总是一样的。有没有办法只为“A”和“B”编写一次代码,然后将相应的类应用(或“继承”)它?
答案 0 :(得分:3)
我能看到你在C#/ Java中实现这一目标的唯一方法是通过组合。考虑一下:
class Foo {
}
interface A {
public void a();
}
interface B {
public void b();
}
class ImplA implements A {
@Override
public void a() {
System.out.println("a");
}
}
class ImplB implements B {
@Override
public void b() {
System.out.println("b");
}
}
class Bar extends Foo {
A a = new ImplA();
public void a() {
a.a();
}
}
class Baz extends Foo {
B b = new ImplB();
public void b() {
b.b();
}
}
class Qux extends Foo {
A a = new ImplA();
B b = new ImplB();
public void b() {
b.b();
}
public void a() {
a.a();
}
}
现在Qux
通过正常继承既具有Foo
的功能,又通过合成具有A
和B
的实现。
答案 1 :(得分:3)
更通用的术语是Mixin。有些语言提供开箱即用的支持,例如Scala和D.虽然有多种方法可以在其他语言中实现相同的结果。
在C#中创建伪mixin的一种方法是使用空接口并为方法提供扩展方法。
interface A { }
static class AMixin {
public static void aFunc(this A inst) {
... //implementation to work for all A.
}
}
interface B { }
static class BMixin {
public static void bFunc(this B inst) {
...
}
}
class Qux : Foo, A, B {
...
}
答案 2 :(得分:1)
这在提供特征的语言中可以实现(这里:scala):
class Foo {
def fooM() {}
}
trait A {
def aFunc() {}
}
trait B {
def bFunc() {}
}
class Bar extends Foo with A {}
class Baz extends Foo with B {}
class Qux extends Foo with A with B {}
因为Scala运行在Java之上(既没有多重继承也没有特性),它被翻译成类似这样的东西(简化) - 这可能是一个提示如何在Java / C#中手动实现它:
class Foo {
}
interface A {
void aFunc();
}
interface B {
void bFunc();
}
class Bar extends Foo implements A {
public void aFunc() {
$A.aFunc();
}
}
class Baz extends Foo implements B {
public void bFunc() {
$B.bFunc();
}
}
class Qux extends Foo implements A, B {
public void aFunc() {
$A.aFunc();
}
public void bFunc() {
$B.bFunc();
}
}
class $A {
public static void aFunc() {}
}
class $B {
public static void bFunc() {}
}
答案 3 :(得分:1)