请给我一些面向对象的正确建议。 从继承类访问属性数据的正确方法是什么。
假设有 3 个类:
public abstract class Vehicle
{
public int Id {get; set; }
public int Wheels {get; set; }
public string Name {get; set; }
public string Color {get; set; }
}
public class Car : Vehicle
{
}
public class Truck : Vehicle
{
public int LoadCapacity {get; set; }
}
我的第一个想法是创建某种存储库,为我提供所需的属性。
我认为我需要两种类型的查询:
- 返回具有特定 ID 的车辆的属性
- 给我特定类型的所有车辆
所以:
public class VehicleRepository
{
ICollection <???> _vehicles;
??? GetVehicle(int Id);
??? GetVehicles(??? vehicleType);
}
那个???是我的未知数。
我的想法是为 IVehicle 添加类似接口(interface)的东西,并用它来实现 Vehicle。 结果将类似于:
public class VehicleRepository
{
ICollection <IVehicle> _vehicles;
IVehicle GetVehicle(int Id);
ICollection <IVehicle> GetVehicles(IVehicle vehicleType);
}
这显然行不通。
public IVehicle GetVehicle(int Id)
{
return _vehicles.First(x=>x.Id == Id);
// The above want compile as the interface has no attributes
}
如果我使用 Vehicle 而不是 IVehicle,'First(x=>x.Id == Id)' 将正常工作,但如果车辆是卡车,它不会返回 'LoadCapacity'。
查看 GetVehicles 函数,我在想:
public ICollection <T> GetVehicles <T> ()
{
var vehicles = _vehicles.Where(???);
return vehicles;
}
对于应该放在那里的内容有点迷茫,但我想避免反射(reflection),只阅读程序集和类类型等。
感谢您的任何建议。
最佳答案
要存储和获取 vericles,您需要做的就是:
class VehicleRepository {
List<Vehicle> vehicles;
}
要检索它们,只需使用 IEnumerable<T>.OfType<U>()
:
VehicleRepository repository = ...
repository.vehicles.OfType<Car>(); // This will get you all of the cars
repository.vehicles.OfType<Truck>(); // This will get you all of the trucks
不过,如果你想花哨一些,你可以制作 VehicleRepository
一个完全属于自己的集合,使其实现 IEnumerable<T>
.考虑:
class VehicleRepository : IEnumerable<Vehicle> {
List<Vehicle> vehicles;
public IEnumerator<Vehicle> GetEnumerator() {
return vehicles.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return this.GetEnumerator();
}
}
然后您可以查询集合本身,如:
public static void Main() {
VehicleRepository repository = ...;
// Notice that we skip accessing the vehicles member
// because by implementing IEnumerable<T> this class
// becomes a collection. Now you can use OfType<T> directly.
repository.OfType<Car>();
}
编辑:做类似 GetVehicleByID
的事情,你可以尝试这样的事情:
class VehicleRepository : IEnumerable<Vehicle> {
List<Vehicle> vehicles;
public Vehicle GetVehicleByID(Int32 id) {
return vehicles[id];
}
}
你也可以使用索引器,像这样:
class VehicleRepository : IEnumerable<Vehicle> {
List<Vehicle> vehicles;
public Vehicle this[Int32 id] {
get { return vehicles[id]; }
}
}
获取LoadCapacity
从卡车上,你所要做的就是这样:
public static void Main() {
VehicleRepository repository = ...
// Assuming index zero is a truck
Truck truck = (Truck)repository.GetVehicleByID(0);
truck.LoadCapacity = ...
}
在不使用反射的情况下获取特定类型的所有项目(当绑定(bind)到 UI 时,即假设您使用 Strings
)的一种作弊方法是匹配 ToString
类型名称的值。例如:
public static void Main() {
VehicleRepository repository = ...
// Assume we're storing off the typename in the UI dropdown.
// so that when the user selects it, we automatically have the correct
// type name we want to filter by.
String truckTypeName = typeof(Truck).GetType().ToString();
// Filter only by those types with a matching type name. Inefficient,
// but it does avoid reflection.
repository.Where(vehicle => vehicle.GetType().ToString() == truckTypeName)
}
关于继承属性类的 c# OO 建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19210847/