接口如何实现多重继承

时间:2011-09-21 10:42:11

标签: c# oop interface

在许多书中都写到接口是多重继承的替代,但我发现它们之间没有任何相似之处。

继承对于代码和功能的可重用性来说非常重要,而且多继承有助于重用多个类中的代码,但是在接口中我没有找到任何这样的功能,除了类可以继承更多比一个界面。

接口只是函数/方法的声明,它本身不包含任何实现部分,因此继承此接口的类必须编写自己的实现代码。

所以我觉得在接口的情况下代码没有任何可重用性。

是否有任何文件或链接可以解答我的疑问,请与您分享。

6 个答案:

答案 0 :(得分:3)

关于代码的可重用性,你是对的。在这方面,多个接口不能替代多重继承。

然而,继承的另一个方面是:它在基类和子类之间建立了is-a关系。因此,继承多个超类的类可以充当其中任何一个。在这方面,接口用作有效的替代,例如,接受接口的方法也将接受实现该接口的任何类,方法与接受从所需类派生的任何类相同。但正如您所说,每个类都必须自己实现接口方法。

示例:

public interface Foo {
    int doFoo();
}

public interface Bar {
    long doBar();
}

public class Baz {
    String doBaz() {
        return "This is baz";
    }
}

public class FooBar extends Baz implements Foo, Bar {
    public long doBar() {
        return 123;
    }
    public int doFoo() {
        return 456;
    }
}

// Accepts interface Bar implementing objects
public void doSomething(Bar b) {
    System.out.println(b.doBar() * 10);
}

// Accepts interface Foo implementing objects
public void doSomethingOther(Foo f) {
    System.out.println(f.doFoo() / 10);
}

// Accepts objects of class Baz and subclasses
public void doMore(Baz b) {
    System.out.println(b.doBaz());
}

void bla() {
    FooBar fb = new FooBar();

    // FooBar can act as Foo, Bar, and Baz
    doSomething(fb);
    doSomethingOther(fb);
    doMore(fb);
}

答案 1 :(得分:2)

你是对的。

人们的意思是C#中的类型可以实现多个接口。这与经典继承不同。

允许你在许多不同的上下文中使用一个类,并且从这样的类继承的任何类当然都能够使用基类实现来重用。

答案 2 :(得分:0)

参见本例。

 /*interface 1 with two methods*/
    interface IA1
    {
        void Foo1();
        void Foo2();
    }   
   /*Interface two with two methods */
    interface IA2
    {
        void Foo1();
        void Foo3();
    }   



 /*class implemeting two interfaces now. Here class cannot inherit two classes but can inherit two interfcaes.*/
  /* Case1 */
    class CA : IA1, IA2  
    { 
        void IA1.Foo1()//Explicitly Implemented
        {
            Console.WriteLine("In IA1.Foo1");
        }
        void IA2.Foo1() //Explicitly Implemented
        {
            Console.WriteLine("In IA2.Foo1");
        }
        public void Foo2()  //Implicitly Implemented
        {
            Console.WriteLine("In IA1.Foo2");
        }
        public void Foo3()  //Implicitly Implemented
        {
            Console.WriteLine("In IA2.Foo3");
        }
    }


 /* Case2*/
    class CA : IA1, IA2   {
        public void Foo1() //Implicitly Implemented
        {
            Console.WriteLine("In Foo1");
        }
        public void Foo2()  //Implicitly Implemented
        {
            Console.WriteLine("In Foo2");
        }
        public void Foo3()  //Implicitly Implemented
        {
            Console.WriteLine("In Foo3");
        }
    }   

使用接口的概念,类可以继承一个或多个接口。并且可以为继承的接口实现自己的功能。

答案 3 :(得分:0)

 Inheritance is mostly important for re-usability of code and functionality 
 and multiple inheritance was helping to re-use code from more than one class, 
 but in Interface I didn't find any such feature except that a class can inherit 
 from more than one interface.

接口确实提升了代码的可重用性(特别是与多态性相结合,继承可以创造奇迹!)。我可以说出接口可能有益的另一种情况:回调。

由于我们在C#中有代理,我怀疑是否有任何C#开发人员将使用接口作为回调媒介(可能是使用C#1.0的C#开发人员)。但是对于Java开发人员来说,他们如何在没有代理的情况下实现回调?答案:接口。

使用代理回调

public delegate int Transformer (int x);

class Util
{
    public static void Transform (int[] values, Transformer t)
    {
        for (int i = 0; i < values.Length; i++)
            values[i] = t (values[i]);
    }
}

class Test
{
    static void Main()
    {
        int[] values = { 1, 2, 3 };
        Util.Transform (values, Square);
        foreach (int i in values)
            Console.Write (i + " "); 
    }

    static int Square (int x) { return x * x; }
}

使用界面进行回调

public interface ITransformer
{
    int Transform (int x);
}

public class Util
{
    public static void TransformAll (int[] values, ITransformer t)
    {
        for (int i = 0; i < values.Length; i++)
            values[i] = t.Transform (values[i]);
    }
}

class Squarer : ITransformer
{
    public int Transform (int x) { return x * x; }
}

static void Main()
{
    int[] values = { 1, 2, 3 };
    Util.TransformAll (values, new Squarer());
    foreach (int i in values)
         Console.WriteLine (i);
}

有关回调的详细信息,请参阅C# Callbacks with Interfaces and DelegatesImplement callback routines in Java

注意:此帖子中的示例代码取自Nutshell中的C#4.0一书(这也是一个很好的C#参考)。

知名开发商警告我们继承的危险:
Allen Holub Why extends is evil Nick Fitzgerald的OOP The Good Parts: Message Passing, Duck Typing, Object Composition, and not Inheritance Eric Gunnerson Seven deadly sins of programming - Sin #2: Overuse of Inheritance

答案 4 :(得分:0)

继承结合了两个有些正交的概念:

  1. 派生类可以隐式使用父类的方法和字段来处理与父类相匹配的行为部分。
  2. 派生类的对象几乎可以用于父类的任何对象。

允许类隐式使用来自多个父类的方法和字段可能会导致一些棘手的问题,例如:如果类X提供了抽象方法foo(),则类Y和Z都继承X并提供foo()的不同实现,而类Q尝试继承Y和Z.如果将类Q的对象o传递给期望的方法一个X(合法的,因为可以使用派生类的对象,可以使用父类的对象),如果该方法尝试调用o.foo()会发生什么?

接口通常不存在此类问题。如果接口IY和IZ继承自包含foo()的接口IX,并且接口IQ继承了这两个接口,则实现IQ的类必须提供IQ.foo()的实现,该实现也将用于IY.foo(), IZ.foo()和IX.foo()。可能会产生不明确的情况,但这会导致编译时发出尖叫声。

答案 5 :(得分:-1)

实际上,除了C#,我没有好的答案,Java没有多重继承,它应该有。接口应该能够取代多重继承的要点就像是重复足够多次成为现实的大谎言。

参数是多重继承会导致所有这些问题,但我一直听到C#这些从未使用过C ++的Java开发人员的论点。我也不记得C ++程序员说“哎呀,我喜欢C ++,但如果他们只能摆脱多重继承,它就会变成一种很棒的语言”。人们在实际时使用它而不是在实际时使用它。

您的问题是多重继承适用的经典案例。任何重构代码的建议都告诉你如何解决C#,Java没有多重继承的问题。

所有关于“哦,代表团更好,la-di-dah”的讨论都让宗教与设计混淆。没有正确的方法。事情要么更有用,要么不那么有用。

在您的情况下,多重继承会更有用,也是更优雅的解决方案。

至于将代码重构为一种不太有用的形式,以满足所有从未使用过多重继承的宗教人士,并相信“多重继承是坏事”,我想你必须降级你的代码因为我看不到C#,Java很快就会以这种方式“改进”。有太多人重复宗教咒语到愚蠢的程度,我无法看到它被添加到语言中。

...但正如您从上面提供的解决方案中可以看到的那样,大多数人认为这样的解决方案将变得过于复杂和混乱!

我宁愿自己冒险进入“x extends a,b”领域,即使它是一个非常可怕的解决方案,可能会压倒大多数C#,Java程序员的能力。

上面建议的解决方案更令人惊讶的是,这里的每个人都建议您将代码重构为“委托”,因为多重继承很糟糕,如果他们遇到同样的问题,会解决问题通过简单地做:“x扩展a,b”并完成它,所有关于“委托与继承”的宗教争论都将消失。整个辩论都是愚蠢的,只有无知的程序员才会提出,他们只能证明他们能够从书中背诵出来的程度,以及他们能为自己多少思考。

如果您认为C#,Java应该拥有它,那么多重继承可以帮助你100%正确,不,你在代码中做错了什么。