简体   繁体   中英

Multiple inheritance without multiple inheritance and without code duplication

I have a theoretical question concerning how to deal with the following scenario in a language which does not allow multiple inheritance.

Imagine I have a base class Foo and from it I am wishing to create three sub-classes:

  • Class Bar inherits Foo and implements functionality "A"
  • Class Baz inherits Foo and implements functionality "B"
  • Class Qux inherits Foo and implements functionalities "A" and "B"

Imagine that the code to implement functionalities "A" and "B" is always the same. Is there a way to write the code for "A" and "B" only once, and then have the appropriate classes apply (or "inherit") it?

Well the only way I can see you achieving this in C#/Java is by composition. Consider this:

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

Now Qux has both the functionality of Foo via normal inheritance but also the implementations of A and B by composition.

The more general term for this is a Mixin . Some languages provide support out of the box, such as Scala and D. There are various ways to achieve the same results in other languages though.

One way you can create a pseudo-mixin in C# is to use empty interfaces and provide the methods with extension methods.

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 {
    ...
}

This is achievable in languages providing traits (here: ):

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 {}

Because Scala runs on top of Java (having neither multiple inheritance nor traits) it is translated into something like this (simplified) - which might be a hint how to implement it in Java/C# manually:

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() {}
}

There are several ways to do something like this. More specifically, if we abandon the inheritance aspect for a moment, there are ways to introduce the same unit of functionality to different classes, while writing the unit only once.

Okay, I love AOP Frameworks, and they exist for many languages (C# and Java having several). AOP Frameworks basically allow you add self-contained functionality into different classes throughout your inheritance structure.

For C#, you have PostSharp and for Java you have AspectJ , among many others.

Many AOP frameworks allow 'hijacking' or 'overriding' method calls without using inheritance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM