[英]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
? 强制从Animal
和IHasLegs
继承的对象? 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
的抽象类,该抽象类继承自Animal
和IHasLegs
。 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
-即,您不能将Lizard
和Donkey
放在使用这个概念的同一个笼子。
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
简单IFoo
和iBar
并声明没有自己的成员,这意味着任何类,它实现IFoo
和IBar
工具的所有成员 IFooBar
,赢得除非将IFooBar
声明为实现它,否则不允许将此类IFooBar
为IFooBar
。 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
已知支持IWagTail
, IMoo
,和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
会执行IWagTail
, it.Self
将实施IMoo
, it.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>>
的对象被期望同时实现IWagTail
和IGiveMilk
,编译器也无法做到这一点。 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.