// 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; }
}
我应该把什么?强制继承Animal
和IHasLegs
的对象?我不希望在该网箱中看到Snake
也不是Table
。
--------------编辑--------------
谢谢大家的答案,但事情是这样的: 我真正想做的是:
public interface IClonable { ... }
public class MyTextBox : TextBox, IClonable { ... }
public class MyComboBox : ComboBox, IClonable { ... }
TextBox / ComboBox当然是一个控件。 现在,如果我创建一个继承Control和IClonable的抽象类,我将松开我需要的TextBox / ComboBox继承。不允许多类继承,因此我必须使用接口。现在我再次想到它,我可以创建另一个继承自IClonable的接口:
public interface IClonableControl : IClonable { ... }
public class MyTextBox : TextBox, IClonableControl { ... }
public class MyComboBox : ComboBox, IClonableControl { ... }
然后
List<IClonableControl> clonableControls;
谢谢!
答案 0 :(得分:17)
首先,Animals
对于类名来说是一个糟糕的选择,它将是Animal
。类名应该是单数。此类也应声明为abstract
,因为它只是Donkey
等具体类型的基类。
其次,您可以定义一个名为LeggedAnimal
的抽象类,该类继承自Animal
和IHasLegs
。然后,您可以从Donkey
等继承LeggedAnimal
最后,你可以说List<LeggedAnimal>
,你就可以了!
答案 1 :(得分:10)
没有List<T where T : Animals, IHasLegs>
的直接概念。您可以将T
向上移动到一个级别 - 然后调用者必须指定满足两个约束的单个T
:
class Cage<T> where T : Animal, IHasLegs {
public List<T> Items {get;set;}
}
例如,它可能是Cage<Lizard>
- 或(单独)Cage<Donkey>
- 但您仍然无法使用它来存储 任何 Animal
有腿 - 即你不能使用这个概念将Lizard
和Donkey
放在同一个笼子里。
答案 2 :(得分:3)
答案 3 :(得分:3)
为什么不制作AnimalwithLegs类?
public abstract class AnimalWithLegs : Animal, IHasLegs{}
然后
public class CageWithAnimalsWithLegs
{
public List<AnimalWithLegs> AnimalWithLegs { get; set; }
}
答案 4 :(得分:1)
给你一个完整的例子..复制粘贴到Visual-Studio并编译。祝你好运:)
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,
};
}
}
答案 5 :(得分:0)
如果您感兴趣的类型的合理数量组合是一种方法,那就是定义从多个接口继承的复合接口。可以为任何接口组合定义复合接口,并使用这种类型作为通用参数。这种方法最大的问题是,即使像IFooBar
这样的界面只是IFoo
和iBar
并且没有宣布自己的成员,也没有办法指明,这意味着任何实现IFoo
和IBar
的类实现了IFooBar
的所有成员,它们不允许将这些类强制转换为IFooBar
除非他们宣称自己是在实施它。因此,在定义实现接口组合的类之前,必须确定一个人感兴趣的接口组合,如果这些类可以被期望这些组合的代码使用。
另一种方法是定义接口ISelf<out T> { T Self {get;}}
,对于许多其他接口(例如IAnimal
),也可以定义例如IAnimalAnd<out T> : IAnimal, ISelf<T> { }
。 Zebra
,并且有任何类型,例如例如IAnimal
IAnimalAnd<Zebra>
也实施Animal
。如果一个人使用该模式并且需要一个已知支持IWagTail
,IMoo
和IGiveMilk
的{{1}}列表,那么执行这些操作的任何Animal
根据模式将实现IWagTailAnd<IMooAnd<IGiveMilkAnd<Animal>>>>
(可以按任何顺序嵌套接口)。如果其中一个具有该类型的引用it
,那么it
将实施IWagTail
,it.Self
将实施IMoo
,it.Self.Self
将实施IGiveMilk
1}},it.Self.Self.Self
将是Animal
。如果it
以通常的方式实现模式,则所有上述引用都将引用相同的对象实例it
,但是作为不同的类型。
对此方法有用的是,使用此模式实现任何接口组合的对象可以转换为嵌套接口类型,表示这些类型的任何子集,无论是否有人认为该特定子集将是在写入类型时很有用。这种方法最大的困难在于即使实现IWagTailAnd<IGiveMilkAnd<Animal>>
的对象应该同时实现IWagTail
和IGiveMilk
,编译器也无法告诉它;它可以告诉对象实现IWagTail
,并且它的Self
属性实现IGiveMilk
,并且可能期望模式的正常实现,即对象{{1} }属性将引用自身(暗示它必须实现Self
),但编译器无法知道。