我还在用OO和C#弄湿我的脚。我确信这是一个简单的问题,我想我知道答案,但我想确定。
如果我有一个名为Car
的类,另一个名为Ford
的类继承自Car
,另一个名为Mustang
的类继承自Ford
}类。
是否可以创建接受Car
个对象集合的方法,然后当我调用该方法时,实际上将Mustang
(或Ford
的集合传递给该方法)对象,因为它们实际上是Car
个对象?
我的想法是,这应该是可能的,理解我只能访问Car
类的Properties \ Methods。我是不是基于这个?
此外,如果我是对的,您可以这样做:您是否需要在调用方法时将Mustang
集合转换为Car
集合?
答案 0 :(得分:3)
不,那是不可能的。
因此,如果我们有一个接受List<Car>
类型的函数。显然,该功能应该能够在该列表中添加Prius
,不是吗?好吧,如果您被允许将List<Mustang>
传递给此方法,那么您刚刚将Prius
添加到List<Mustang>
,显然这很糟糕。
现在,如果该方法的参数为List
或某些其他只读集合类型,而不是传递IEnumerable
,那么它可能是“协变”。在这种情况下,作为示例,您可以接受IEnumerable<Car>
并将其传递给List<Mustang>
,因为您永远不会添加到列表中,您只能访问各种元素,并且只要Mustang
个对象是Car
个对象,这不是问题。
设计似乎有点......关闭。我不认为Ford
应该继承Car
。 Ford
不是汽车,而是品牌,公司,汽车类型。 Mustang
是汽车,因此从一个汽车继承是有道理的。我会创建一个新类型,比如Manufacturer
,您可以创建Ford
,Toyota
等,并将其设为{只读} Car
的属性。
答案 1 :(得分:1)
如果您只想访问Car
课程中的方法和属性,则没有理由传递Mustangs
列表。相反,您应该只是处理Mustangs
,就好像它们是Cars
一样。这是继承的主要要点之一。您只需创建一个类型为car List<Car>
的列表,然后将Mustangs
添加到其中。然后传递类型Car
的列表。这是更具可扩展性的,因为它可以接受任何继承自Car
的对象,并且因为您只使用Car
中的属性/方法,所以它与您需要的定义一样严格。
如果您想在Mustang
类中使用特定行为,但是用于调用该行为的公共接口在Car
中定义方法,则在Mustang
中覆盖它。同样,这更具可扩展性,因为当您创建NineEleven
类时,您还可以覆盖此方法,从而在子类中提供不同的行为,而不会实际暴露其类型。
答案 2 :(得分:1)
其他人已经解释了将Mustangs集合作为参数发送到不同方法的各个方面,然后我将添加一些您可能会觉得有用的信息。
如果您有一系列汽车List<Car>
,您只能通过以下方式获取野马:
IEnumerable<Mustang> mstngs = cars.OfType<Mustang>();
List<Mustang> mstngsLst = mstngs.ToList();
如果你有一系列Mustangs List<Mustang>
,你可以将它们全部投入汽车:
IEnumerable<Car> cars = mstngs.Cast<Car>();
List<Car> carsLst = cars.ToList();
顺便说一下,转换回列表不是必须的。这取决于你需要对集合做什么。
答案 3 :(得分:0)
您可以执行此操作,传递包含List<Car>
:s的Ford
,例如:
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() {}
}