简体   繁体   English

C#同时声明类和接口

[英]C# declare both, class and interface

// interface
public interface IHasLegs { ... }

// base class
public class Animal { ... }

// derived classes of Animal
public class Donkey : Animal, IHasLegs { ... } // with legs
public class Lizard : Animal, IHasLegs { ... } // with legs
public class Snake : Animal { ... } // without legs

// other class with legs
public class Table : IHasLegs { ... }

public class CageWithAnimalsWithLegs {
    public List<??> animalsWithLegs { get; set; }
}

What should I put in the ?? 我应该放什么?? to force objects that inherit from both Animal and IHasLegs ? 强制从AnimalIHasLegs继承的对象? I don't want to see a Snake in that cage neither a Table . 我不想在那个笼子里看到Snake ,也不是Table

-------------- EDIT -------------- --------------编辑--------------

Thank you all for your answers, but here is the thing: What I actually want to do is this: 谢谢大家的回答,但事情是这样的:我实际上想要做的是:

public interface IClonable { ... }
public class MyTextBox : TextBox, IClonable { ... }
public class MyComboBox : ComboBox, IClonable { ... }

TextBox/ComboBox is of course a Control. TextBox / ComboBox当然是一个控件。 Now if I make an abstract class that inherits both Control and IClonable, I will loose the TextBox/ComboBox inheritance that I need. 现在,如果我创建一个既继承Control又继承IClonable的抽象类,则将失去所需的TextBox / ComboBox继承。 Multiple class inheritance is not allowed, so I have to work with interfaces. 不允许多类继承,因此我必须使用接口。 Now that I think of it again, I could create another interface that inherits from IClonable: 现在,我再次考虑它,我可以创建另一个继承自IClonable的接口:

public interface IClonableControl : IClonable { ... }
public class MyTextBox : TextBox, IClonableControl { ... }
public class MyComboBox : ComboBox, IClonableControl { ... }

and then 然后

List<IClonableControl> clonableControls;

Thank you!! 谢谢!!

First of all, Animals is a bad choice for a class name, it would be Animal . 首先,对于类名来说, Animals是一个不好的选择,那就是Animal Class names should be in singular. 类名应为单数。 This class should also be declared abstract , because it is just a base class for concrete types such as Donkey . 此类也应声明为abstract ,因为它只是具体类型(例如Donkey的基类。

Second, you can define an abstract class named LeggedAnimal that inherits from Animal and IHasLegs . 其次,可以定义一个名为LeggedAnimal的抽象类,该抽象类继承自AnimalIHasLegs And then you can inherit Donkey from LeggedAnimal , etc. 然后您可以从LeggedAnimal等继承Donkey

Finally, you can then say List<LeggedAnimal> and you're good to go! 最后,您可以说List<LeggedAnimal> ,您就可以开始了!

There is no direct concept of a List<T where T : Animals, IHasLegs> . 没有List<T where T : Animals, IHasLegs>直接概念, List<T where T : Animals, IHasLegs> You can move the T up a level, to the cage - but then the caller must specify an individual T that satisfies both constraints: 您可以将T向上移动到笼子中-但呼叫者必须指定一个同时满足两个约束的T

class Cage<T> where T : Animal, IHasLegs {
    public List<T> Items {get;set;}
}

It could be a Cage<Lizard> , for example - or (separately) a Cage<Donkey> - but you still could not use this to store any Animal that has legs - ie you couldn't put a Lizard and a Donkey in the same cage using this concept. 例如,它可以是Cage<Lizard> -或(单独)是Cage<Donkey> -但您仍然不能使用它来存储任何具有腿的Animal -即,您不能将LizardDonkey放在使用这个概念的同一个笼子。

  1. I think that Animal is an abstract class and hence needs to be called IAnimal. 我认为Animal是一个抽象类,因此需要称为IAnimal。
  2. Create a new type IAnimalWithLegs that inherits from both IhasLegs and IAnimal. 创建一个继承自IhasLegs和IAnimal的新类型IAnimalWithLegs。
  3. Use the newly created type as the type of the list. 使用新创建的类型作为列表的类型。

Why Don't you make a class AnimalwithLegs? 您为什么不上动物课?

public abstract class AnimalWithLegs : Animal, IHasLegs{}

then 然后

public class CageWithAnimalsWithLegs 
{
   public List<AnimalWithLegs>  AnimalWithLegs { get; set; }
}

Gave you a full example.. copy-paste to Visual-Studio and compile. 给你一个完整的例子。复制粘贴到Visual Studio并编译。 Good Luck :) 祝好运 :)

 internal class Program
    {
        // interface
        public interface IHasLegs {}

        // base class
        public class Animal {}

        public class AnimalWithLegs : Animal, IHasLegs {}

        // Animals
        public class Donkey : AnimalWithLegs {}

        public class Lizard : AnimalWithLegs {}

        public class Snake : Animal {}

        // example of inanimte objects. (lifeless)
        public class Table : IHasLegs {}

        public class Desk : Table {}

        public class ConferenceTable : Table {}

        //public class Wife : BrainLessObject{} //hmm.. wrong place.. dilemma..

        //example for cages
        public class ListOfIhasLegs : List<IHasLegs> {}

        public class ListOfAnimals : List<Animal> {}

        public class ListOfAnimalsWithLegs : List<AnimalWithLegs> {}

        // usage examples.
        private static void Main(string[] args)
        {
            var donkeyInstance = new Donkey();
            var lizardInstance = new Lizard();
            var snakeInstance = new Snake();

            var tableInstance = new Table();
            var deskInstance = new Desk();
            var conferenceTalbeInstance = new ConferenceTable();

            var listOfThingsWithLegs = new ListOfIhasLegs
            {
                donkeyInstance,
                lizardInstance,
                tableInstance,
                deskInstance,
                conferenceTalbeInstance
            };

            var listOfAnimals = new ListOfAnimals
            {
                donkeyInstance,
                lizardInstance,
                snakeInstance
            };

            var cageOfAnimalsWithLegs = new ListOfAnimalsWithLegs
            {
                donkeyInstance,
                lizardInstance,
            };
        }

    }

One approach if there's a reasonable number of combinations of types you're interested in is to define composite interfaces which inherit from multiple interfaces. 如果您感兴趣的类型组合数量合理,一种方法是定义从多个接口继承的复合接口。 One may define a composite interface for any combination of interfaces, and use such a type as a generic parameter. 可以为接口的任何组合定义一个复合接口,并使用这种类型作为通用参数。 The biggest problem with this approach is that there's no way to specify that even if an interface like IFooBar simply IFoo and iBar and declares no members of its own, meaning any class which which implements IFoo and IBar implements all the members of IFooBar , that won't allow such classes to be cast to IFooBar unless they declare themselves as implementing it. 这种方法的最大问题是,有没有办法来指定,即使等的接口IFooBar简单IFooiBar并声明没有自己的成员,这意味着任何类,它实现IFooIBar工具的所有成员 IFooBar ,赢得除非将IFooBar声明为实现它,否则不允许将此类IFooBarIFooBar Consequently, one must decide what combinations of interfaces one is interested in before defining classes that implement those combinations of interfaces, if those classes are to be usable by code expecting those combinations. 因此,在定义实现那些接口组合的类之前,如果那些类可以通过期望那些组合的代码使用,则必须确定一个接口所感兴趣的组合。

An alternative approach is to define an interface ISelf<out T> { T Self {get;}} , and for many of your other interfaces (eg IAnimal ) also define eg IAnimalAnd<out T> : IAnimal, ISelf<T> { } , and have any type eg Zebra which implements eg IAnimal also implement IAnimalAnd<Zebra> . 另一种方法是定义一个接口ISelf<out T> { T Self {get;}} ,对于您的许多其他接口(例如IAnimal )也定义例如IAnimalAnd<out T> : IAnimal, ISelf<T> { } ,和具有任何类型的例如Zebra ,它实现例如IAnimal也实现IAnimalAnd<Zebra> If one uses that pattern and needs a list of Animal which are known to support IWagTail , IMoo , and IGiveMilk , then any Animal which does those things according to the pattern will implement IWagTailAnd<IMooAnd<IGiveMilkAnd<Animal>>>> (one may nest the interfaces in any order). 若用该模式,需要的列表Animal已知支持IWagTailIMoo ,和IGiveMilk ,那么任何Animal根据图案将实施这确实那些东西IWagTailAnd<IMooAnd<IGiveMilkAnd<Animal>>>> (一个可以任何顺序嵌套接口)。 If one has a reference it of that type, then it will implement IWagTail , it.Self will implement IMoo , it.Self.Self will implement IGiveMilk , and it.Self.Self.Self will be an Animal . 如果一个具有基准it这种类型的,那么it会执行IWagTailit.Self将实施IMooit.Self.Self将实施IGiveMilk ,和it.Self.Self.Self将是一个Animal If it implements the pattern in the usual fashion, all of the above references will refer to the same object instance it , but as different types. 如果it实现了在通常的方式的模式,上述所有引用将指向同一个对象实例it ,但作为不同的类型。

What's helpful with this approach is that an object which implements any combination of interfaces using this pattern may be cast to nested interfaces type which represents any subset of those types, whether or not anyone thought that particular subset would be useful when the type was written. 这种方法的有用之处在于,可以将使用此模式实现接口的任意组合的对象转换为表示这些类型的任何子集的嵌套接口类型,无论是否有人认为编写该类型时该特定子集将是有用的。 The biggest difficulty with this approach is that even though an object which implements IWagTailAnd<IGiveMilkAnd<Animal>> is expected to implement both IWagTail and IGiveMilk , the compiler can't tell that; 这种方法最大的困难在于,即使实现IWagTailAnd<IGiveMilkAnd<Animal>>的对象被期望同时实现IWagTailIGiveMilk ,编译器也无法做到这一点。 it can tell that the object implements IWagTail , and that its Self property implements IGiveMilk , and one might expect that normal implementations of the pattern, the object's Self property will refer to itself (implying that it must implement IGiveMilk ), but the compiler can't know that. 它可以告诉该对象实现IWagTail ,并且其Self属性实现IGiveMilk ,并且可以期望该模式的常规实现(对象的Self属性将引用自身)(这意味着它必须实现IGiveMilk ),但是编译器可以不知道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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