2012-05-27 12 views
5

Aşağıdaki senaryoyu birden çok devralmaya izin vermeyen bir dilde ele alma konusunda teorik bir sorum var.Birden fazla kalıtım olmadan ve kod çoğaltması olmadan birden fazla kalıtım

ben bir temel sınıf Foo var düşünün ve ondan ben üç alt sınıfları oluşturmak isteyen ediyorum:

  • Sınıf BarFoo devralır ve işlevselliği uygulayan "A"
  • Sınıf Baz, Foo ve işlevselliğini uygular "B" işlevselliği
  • Sınıf QuxFoo devralır ve işlevleri, "A" ve "B"

kod işlevleri "A" ve "B" uygulama düşünün uygulayan her zaman aynıdır. "A" ve "B" kodlarını yalnızca bir kez yazmak için bir yol var mı ve daha sonra uygun sınıflar geçerli mi (yoksa "miras") var mı?

+0

Herhangi bir dil? Java? C#? Başka bir şey? – Tudor

+0

Neden FOO sınıfınızda aynı işlevselliği uyguluyorsunuz ve sadece A/B'yi sanal/geçersiz olarak işaretliyorsunuz? – YavgenyP

+0

@Tudor C# 'da düşünmekteyken, birden fazla kalıtımın yapılmasına izin vermeyen herhangi bir OOP dili. –

cevap

3

Eh tek yolu/Java kompozisyon gereğidir: hangi el ile Java/C# nasıl uygulanacağı konusu bir ipucu olabilir. Şunu bir düşünün:

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

Şimdi Qux Normal miras yoluyla Foo işlevselliğini değil, aynı zamanda kompozisyon tarafından A ve B uygulamalarını hem sahiptir.

1

Bu diller özellikleri sağlayan ulaşılabilir olduğunu (burada: ):

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 (çoklu kalıtım ne de özellikleri ne sahip) böyle bir şey haline çevrilmiştir üstünde çalıştığı için (basitleştirilmiş) - sana C# bunu başarmak görebilirsiniz

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

Bunun için daha genel bir terim Mixin'dur. Bazı diller Scala ve D gibi kutudan destek sağlar. Diğer sonuçlarda da aynı sonuçları elde etmenin çeşitli yolları vardır.

C# biçiminde bir sözdizimi oluşturabilmenin bir yolu, boş arabirimleri kullanmak ve yöntemleri uzantı yöntemleriyle sağlamaktır.

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

Böyle bir şey yapmanın birkaç yolu vardır. Daha spesifik olarak, bir an için miras yönünü terk edersek, üniteyi sadece bir kez yazarken aynı birim işlevini farklı sınıflara tanıtmanın yolları vardır.

Tamam loveAOP Pek çok dil (C# ve Java birden fazla) için var. AOP Çerçeveleri temel olarak, miras yapınız boyunca kendi kendine yeten işlevselliği farklı sınıflara eklemenize izin verir.

C# için, PostSharp var ve Java için AspectJ, diğerleri arasında.

Birçok AOP çerçevesi, miras kullanmadan "çağrıları" veya "geçersiz kılma" yöntem çağrılarına izin verir.