7
// 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; }
}

我应该在里面放什么??强制从两者继承的对象AnimalIHasLegs?我不想Snake在那个笼子里看到 a 也不想看到 a 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;

谢谢!!

4

6 回答 6

17

首先,Animals对于类名来说是一个糟糕的选择,它会是Animal. 类名应该是单数。这个类也应该被声明abstract,因为它只是具体类型的基类,例如Donkey.

其次,您可以定义一个名为的抽象类LeggedAnimal,它继承自AnimalIHasLegs。然后你可以继承DonkeyLeggedAnimal,等等。

最后,你可以说List<LeggedAnimal>,你很高兴去!

于 2013-10-29T14:14:27.610 回答
10

没有直接的 a 概念List<T where T : Animals, IHasLegs>。您可以将T上一级移动到笼子 - 但是调用者必须指定一个T满足这两个约束的个人:

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

例如,它可以是 a Cage<Lizard>- 或(单独) a Cage<Donkey>- 但你仍然不能使用它来存储任何 Animal有腿的东西 - 即你不能使用这个概念将 aLizard和 aDonkey放在同一个笼子里。

于 2013-10-29T14:15:22.803 回答
3
  1. 我认为 Animal 是一个抽象类,因此需要称为 IAnimal。
  2. 创建一个继承自 IhasLegs 和 IAnimal 的新类型 IAnimalWithLegs。
  3. 使用新创建的类型作为列表的类型。
于 2013-10-29T14:15:00.843 回答
3

你为什么不创建一个 AnimalwithLegs 类?

public abstract class AnimalWithLegs : Animal, IHasLegs{}

然后

public class CageWithAnimalsWithLegs 
{
   public List<AnimalWithLegs>  AnimalWithLegs { get; set; }
}
于 2013-10-29T14:18:05.703 回答
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,
            };
        }

    }
于 2013-10-29T14:40:19.950 回答
0

如果您感兴趣的类型组合数量合理,一种方法是定义从多个接口继承的复合接口。可以为任何接口组合定义一个复合接口,并将这种类型用作泛型参数。这种方法的最大问题是没有办法指定即使一个IFooBar简单的接口IFooiBar和声明没有它自己的成员,这意味着任何实现IFooIBar实现所有成员IFooBar类,也不允许这样的类被投到IFooBar除非他们声明自己正在实施它。因此,在定义实现这些接口组合的类之前,必须决定对哪些接口组合感兴趣,如果这些类要被期望这些组合的代码使用的话。

另一种方法是定义一个接口ISelf<out T> { T Self {get;}},并且对于您的许多其他接口(例如IAnimal)也定义例如IAnimalAnd<out T> : IAnimal, ISelf<T> { },并具有任何类型,例如Zebra实现例如IAnimal也实现IAnimalAnd<Zebra>。如果一个人使用该模式并且需要一个Animal已知支持IWagTailIMoo和的列表IGiveMilk,那么Animal根据该模式执行IWagTailAnd<IMooAnd<IGiveMilkAnd<Animal>>>>这些操作的任何一个都将实现(可以以任何顺序嵌套接口)。如果一个人有it该类型的引用,那么it将实现IWagTailit.Self将实现IMooit.Self.Self将实现IGiveMilk,并且it.Self.Self.Self将是一个Animal。如果it以通常的方式实现模式,所有上述引用将引用相同的对象实例it,但作为不同的类型。

这种方法的有用之处在于,使用此模式实现任何接口组合的对象可以转换为表示这些类型的任何子集的嵌套接口类型,无论是否有人认为在编写该类型时该特定子集会很有用。这种方法的最大困难是,即使一个实现的对象IWagTailAnd<IGiveMilkAnd<Animal>>期望同时实现IWagTailand IGiveMilk,编译器也无法判断;它可以告诉对象实现了IWagTail,并且它的Self属性实现了IGiveMilk,并且人们可能期望模式的正常实现,对象的Self属性将引用自身(暗示它必须实现IGiveMilk),但编译器不知道这一点。

于 2013-10-29T21:21:49.733 回答