4

我仍然对 OO 和 C# 感到困惑。我确信这是一个简单的问题,我想我知道答案,但我想确定一下。

如果我有一个名为的类Car和另一个Ford继承自的类Car,以及另一个Mustang继承自该类的Ford类。

创建一个接受Car对象集合的方法,然后当我调用该方法时实际上将Mustang(或Ford)对象的集合传递给该方法,因为它们实际上是Car对象,是否可以接受/可能?

我的想法是这应该是可能的,因为我知道我只能访问Car类的 Properties\Methods。我是否基于此?

另外,如果我是对的,您可以这样做:您是否需要在调用该方法时将Mustang集合转换为集合?Car

4

4 回答 4

5

不,那是不可能的。

因此,如果我们有一个接受List<Car>类型的函数。显然,该函数应该能够将 a 添加Prius到该列表中,不是吗?好吧,如果您被允许将 a 传递List<Mustang>给此方法,那么您只是将 a 添加Prius到 a List<Mustang>,显然那会很糟糕。

List现在,如果该方法不是传递 a ,而是IEnumerable具有某个其他只读集合类型的参数或其中一个参数,那么它可能是“协变的”。在这种情况下,作为示例,您可以接受 anIEnumerable<Car>并传递它,List<Mustang>因为您从不添加到列表中,您只是访问各种元素,并且只要所有Mustang对象都是Car没有问题的对象。

设计也似乎有点……过时了。我不认为Ford应该继承自Car. Ford不是汽车,它是一个品牌、一个公司、一种汽车。 Mustang 是一辆车,所以从一个继承它是有意义的。我会创建一个新类型,比如说Manufacturer您可以创建Ford,Toyota等,并将其设为 . 的(只读)属性Car

于 2012-11-26T20:38:27.083 回答
1

其他人已经解释了将 Mustangs 集合作为参数发送到不同方法的各个方面,然后我将添加一些您可能会觉得有用的信息。

如果您有一系列汽车List<Car>,您只能通过以下方式获得野马:

IEnumerable<Mustang> mstngs = cars.OfType<Mustang>();
List<Mustang> mstngsLst = mstngs.ToList();

如果您有一系列野马List<Mustang>,您可以将它们全部投入汽车:

IEnumerable<Car> cars = mstngs.Cast<Car>();
List<Car> carsLst = cars.ToList();

顺便说一句,转换回列表不是必须的。这取决于您需要对集合做什么。

于 2012-11-26T20:45:06.500 回答
0

你可以这样做,传递一个List<Car>包含Ford:s 例如:

public void Test()
{
    // This works:
    var fords = new List<Car> {new Ford()};
    FixCars(fords);

    // This does not work (since you cannot pass non car-typed list):
    // var mustangs = new List<Ford> {new Ford()};
    // FixCars(fords);
}

public void FixCars(List<Car> cars)
{
    // Do stuff, for example check actual type and do specialized things:
    foreach (var car in cars)
    {
        var ford = car as Ford;
        if (ford != null)
            ford.Honk();
    }
}

public class Car 
{    
}

public class Ford : Car
{
    public void Honk() {}
}
于 2012-11-26T20:44:46.157 回答
0

如果您只打算访问Car类中的方法和属性,则没有理由传递Mustangs. 相反,您应该Mustangs像对待他们一样对待您的Cars。这是继承的要点之一。您可以简单地创建汽车类型列表,List<Car>然后将您的添加Mustangs到其中。然后传递 type 的列表Car。这更具可扩展性,因为它可以接受任何继承自的对象,Car并且因为您只使用它的属性/方法,Car所以您需要的定义非常严格。

如果您想要Mustang类中的特定行为,但需要一个用于调用该行为的通用接口,请在中定义方法,Car然后在中覆盖它Mustang。同样,这更具可扩展性,因为当您创建一个NineEleven类时,您还可以覆盖此方法,从而在子类中为您提供不同的行为,而无需实际公开它们的类型。

于 2012-11-26T20:43:56.000 回答