5

我有一个关于如何用不允许多重继承的语言处理以下场景的理论问题。

想象一下,我有一个基类Foo,我希望从中创建三个子类:

  • Bar继承Foo并实现功能“A”
  • Baz类继承Foo并实现功能“B”
  • Qux类继承Foo并实现功能“A”和“B”

想象一下实现功能“A”和“B”的代码总是相同的。有没有办法只为“A”和“B”编写一次代码,然后应用适当的类(或“继承”)它?

4

4 回答 4

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

于 2012-05-27T13:07:28.497 回答
3

更通用的术语是Mixin。一些语言提供开箱即用的支持,例如 Scala 和 D。不过,有多种方法可以在其他语言中实现相同的结果。

在 C# 中创建伪混合的一种方法是使用空接口并为方法提供扩展方法。

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 {
    ...
}
于 2012-05-27T14:02:26.757 回答
1

这在提供特征的语言中是可以实现的(这里:):

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() {}
}
于 2012-05-27T13:03:03.693 回答
1

有几种方法可以做这样的事情。更具体地说,如果我们暂时放弃继承方面,有一些方法可以将相同的功能单元引入不同的类,而只需编写一次该单元。

好的,我喜欢 AOP框架,它们适用于多种语言(C# 和 Java 有几种)。AOP 框架基本上允许您将自包含功能添加到整个继承结构中的不同类中。

对于 C#,您有PostSharp,对于 Java,您有AspectJ等等。

许多 AOP 框架允许在不使用继承的情况下“劫持”或“覆盖”方法调用。

于 2012-05-27T14:20:23.057 回答