使用与多重继承相关的接口的任何真实示例

Posted

技术标签:

【中文标题】使用与多重继承相关的接口的任何真实示例【英文标题】:Any real example of using interface related to multiple inheritance 【发布时间】:2010-12-28 03:26:56 【问题描述】:

我正在尝试理解接口,以便我可以在我的程序中实现它们,但我无法想象我应该如何使用它们。 也给我一些在 C# 中使用多重继承的例子

【问题讨论】:

C# 中不存在多重继承。您只能从一个类派生,但您可以实现任意数量的接口。 嗯,实现接口可以看作是接口的多重继承,而不是实现。这是一个灰色地带。 @cwap: 既然是一个注重交互的界面,更多的是实现,我明白你为什么这么想。我经常听到它解释了@dsimcha 的评论方式,所以我并不感到困惑。 【参考方案1】:

注意:接口用于不惜一切代价限制和访问来自不同类的方法或事件等,这意味着我们可以在任何类中定义更多方法但是当我们通过接口调用方法时,意味着我们只想要限制以外的方法方法。在下面的程序中,用户 1 可以同时使用读取和写入,但用户 2 可以写入和执行。看下面这个程序............

namespace ExplConsole

    class Program 
    
        static void Main ()
        
            System.Console.WriteLine("Permission for User1");
            User1 usr1 = new Test(); // Create instance.
            usr1.Read(); // Call method on interface.
            usr1.Write();
            System.Console.WriteLine("Permission for User2");
            User2 usr2 = new Test();
            usr2.Write();
            usr2.Execute();
            System.Console.ReadKey();
        
    
    interface User1
    
        void Read();
        void Write();
    
    interface User2
    
        void Write();
        void Execute();
    
    class Test : NewTest,User1, User2 
    
        public void Read()
        
            Console.WriteLine("Read");
        
        public void Write()
        
            Console.WriteLine("Write");
        
    
    class NewTest 
    
        public void Execute()
        
            Console.WriteLine("Execute");
        
    

输出:

    Permission for User1
    Read
    Write
    Permission for User2
    Write
    Execute

【讨论】:

【参考方案2】:

接口只是为您的对象定义公共元素(例如属性、方法、事件)的契约,而不是行为。

interface IDog

    void WagTail();    //notice no implementation
    ISound Speak();    //notice no implementation


class Spaniel : IDog

    public void WagTail()
    
        Console.WriteLine("Shook my long, hairy tail");
    

    public ISound Speak()
    
        return new BarkSound("yip");
    



class Terrier : IDog

    public void WagTail()
    
        Console.WriteLine("Shook my short tail");
    

    public ISound Speak()
    
        return new BarkSound("woof");
    

更新

在“真实示例”中,我使用以下接口: - 单元测试 - GENERICS(例如存储库、网关、设置)

interface Repository<T>
    T Find(Predicate<T>);
    List<T> ListAll();


interface Gateway<T>
    T GetFrom(IQuery query);
    void AddToDatabase(IEntity entityItem);


interface Settings<T>
    string Name  get; set; 
    T Value  get; set; 
    T Default  get; 

【讨论】:

不完全是我所说的“真实示例”...只是我的看法,但是这些示例(狗、猫、汽车和其他抽象)往往无法帮助任何人理解 OOP概念。 对不起,这不是你的好例子。我试图专注于与抽象基类的比较。请参阅 UPDATE 标记后的想法。【参考方案3】:

接口的一个很好的例子是存储库模式。您的接口将定义 Get、GetAll、Update、Delete 等方法。没有实现,只是函数签名。

然后,您可以编写该类的“具体”实现,以使用 mysql。不过,您的 UI 应该只引用界面。

稍后,如果您决定改用 Microsoft SQL,您可以编写另一个具体的实现,但您的 UI 代码不必更改(太多)。

在 C# 中不存在多重继承,因为您只能从一个“具体”类继承;尽管您可以继承(或“实现”)任意数量的接口。

【讨论】:

【参考方案4】:

我正在编写一个视频游戏。在这个视频游戏中,我对游戏中的对象施加不同的力。推力、冲击力、重力。虽然它们的计算方式不同,但它们都具有相同的基本元素。我需要调用一个更新函数来评估力并将力添加到它所连接的对象。

所以,我所做的是创建一个 IForce 接口,该接口具有更新函数的签名。我所有的部队都实现了这个接口:

public interface IForce

    void Update(Particle particle, GameTime gameTime);

这是一个示例实现。

public class Spring : IForce

    private Particle ThisParticle;
    private Particle ThatParticle;

    private float K;

    public Spring(Particle thisParticle, Particle thatParticle, float k)
    
        ThisParticle = thisParticle;
        ThatParticle = thatParticle;
    

    public void Update(Particle particle, GameTime gameTime)
                
        float X = Vector3.Length(ThisParticle - ThatParticle);

        ThisParticle.Forces.Add(K * X);
    

更新功能有一个简化的弹簧力更新,更容易理解。

这在几个方面有所帮助。

我可以完全改变力的计算方式,而不会影响我代码的其他部分。我一直这样做。同样,我很容易添加新的力量。只要它实现了 IForce 接口,我就知道它会与我现有的代码很好地融合。

它的另一种帮助方式是处理大量的力。我有一个包含 IForce 列表的强制注册表。由于所有部队都实现了该接口并具有更新功能,因此在我的游戏中更新所有部队非常容易。当我创建力时,我将其添加到列表中。然后,我遍历列表并调用每个元素更新函数,而不用担心它是什么类型的力以及我所有的力更新。

我每天都会在很多不同的情况下使用界面。他们太棒了!

【讨论】:

这个场景很好理解接口,但我需要在你解释的场景中通过一点实现来进一步澄清。我无法想象你是如何在课堂上实施这些力量的。我认为您需要在您已经说过的 Interface IForce 中给出 ur 函数的签名。但是您如何在不同的课程中使用它。您是否在所有实现这些力的类中编写这些函数的定义。【参考方案5】:

在我看来,简单的答案是,在一个类中实现一个接口本质上意味着:“这个类必须在接口中定义函数(和参数)”。

由此可知,只要某个类实现了接口,您就可以确定自己能够调用这些函数。

如果多个不同的类实现同一个接口,您可以将它们全部“强制转换”到接口并调用它们上的所有接口函数,这可能会产生不同的效果,因为每个类可能有不同的实现功能。

例如,我一直在创建一个程序,它允许用户生成 4 种不同类型的地图。为此,我创建了 4 种不同类型的生成器类。它们都实现了“IGenerator”接口:

public interface IGenerator 
    public void generateNow(int period);

这告诉他们至少定义一个“public generateNow(int period)”函数。

无论我最初拥有什么生成器,在我将其转换为“IGenerator”之后,我都可以在其上调用“generateNow(4)”。我不必确定我返回的是什么类型的生成器,这基本上意味着,不再有巨大的 if 语句中的“variable instanceof Class1”、“variable instanceof Class2”等。

【讨论】:

我没听懂你,究竟是什么想让我清楚。对于我提出的问题,这个例子似乎正朝着正确的方向发展,但仍然有点怀疑你如何在不同的不同类中使用它,正如你所说的那样——“我回来了,这基本上意味着,不再有”变量 instanceof Class1”、“Class2 的变量实例”等”我无法想象您如何使用此界面来受益于您的代码以及多个界面【参考方案6】:

有时过于抽象会妨碍您,而参考实现细节实际上可以澄清事情。因此,我将提供接近金属的接口解释,让我最终摸索它们。

接口只是声明一个类实现了一些虚函数以及这些虚函数应该如何在类的vtable 中布局的一种方式。当你声明一个接口时,你实际上是在给编译器一个虚函数表的高级描述。当你实现一个接口时,你是在告诉编译器你想在你的类中包含那个接口引用的虚表。

接口的目的是可以将实现接口 I 的类隐式转换为接口 I 的实例:

interface I 
    void doStuff();


class Foo : I 
    void doStuff() 

    void useAnI(I i) 


var foo = new Foo();
I i = foo;  // i is now a reference to the vtable pointer for I in foo.
foo.useAnI(i);  // Works.  You've passed useAnI a Foo, which can be used as an I.

【讨论】:

我怀疑 C# 初学者是否了解 vtables :-) 你可能是对的,尽管在我理解函数指针和 vtable 之前,我什至没有深入了解 OO。这就是我的观点,即参考实现细节实际上可以澄清事情。在我理解函数指针和 vtable 之前,OO 似乎过于抽象和随意。【参考方案7】:

多重继承就是让一个类在多种情况下可用:[伪代码]

interface Shape 
    // shape methods like draw, move, getboundingrect, whatever.


interface Serializable 
    // methods like read and write


class Circle : public Shape, public Serializable 
    // TODO: implement Shape methods
    // TODO: implement Serializable methods


// somewhere later

    Circle circle;
    // ...
    deserializer.deserialize(circle);
    // ...
    graphicsurface.draw(circle);
    // ...
    serializer.serialize(circle);

这个想法是您的 Circle 类实现了两个不同的接口,它们在非常不同的情况下使用。

【讨论】:

这不是多重继承,只是多个接口的实现。 C# 不支持多重继承,也不应该。【参考方案8】:

看看你熟悉的东西 - 即 C# 中的 List 集合。列表定义 IList 接口,通用列表定义 IList 接口。 IList 公开了 Add、Remove 等函数,List 实现了这些函数。还有一些 BindingLists 以稍微不同的方式实现 IList。

我也会推荐Head First Design Patterns。代码示例使用 Java 编写,但很容易翻译成 C#,此外,它们还将向您介绍接口和设计模式的真正力量。

【讨论】:

【参考方案9】:

这是一个(在 Java 中,但这并不重要,因为它们很相似): 在我的项目中,我创建了简单的界面:

public interface Identifiable<T> 
    public T getId();

这是对某些注释的简单替换。下一步:我已经让所有实体类都实现了这个接口。

第三步,写一些类似语法糖的方法:

public <T> List<T> ids(List<? extends Identifiable<T> entities)  ... 

这只是一个例子。

更复杂的示例类似于验证规则:您有一些验证引擎(可能由您编写)和一个简单的规则接口:

public interface ValidationRule 
    public boolean isValid(...);

因此,此引擎需要您实施规则。当然会有多重继承,因为你当然希望不止一条规则。

【讨论】:

以上是关于使用与多重继承相关的接口的任何真实示例的主要内容,如果未能解决你的问题,请参考以下文章

来自两个派生类的多重继承

为啥要使用接口,多重继承与接口,接口的好处?

C++的多重继承

J a v a 的“多重继承”

java中的多重继承是啥意思?

vb.net:接口中的多重继承