C#中的泛型和继承类型
本文关键字:继承 类型 泛型 | 更新日期: 2023-09-27 18:21:04
我对处理这种特殊情况的最佳方法有点困惑。我对使用泛型还没有100%的信心。
我有一个类Model
,它有两个派生类型,3DModel
和2DModel
。
我在View
类的Model
中有一个抽象属性,它也有两个派生类型,3DView
和2DView
。
当3DModel
调用View
属性时,我希望返回3DView
,据我所知,这就是泛型的作用(目前2D和3D版本只有自己的属性和派生类型)。
我的问题是,要做到这一点,我认为我需要将Model
更改为Model<TView>
,然后在3DModel
和2DModel
中提供一个where。不过,这需要更改Model
、2DModel
和3DModel
的每次使用来适应这种情况,而且它在任何地方都被使用(据我所知,包括无法将Model
的实例转换为3DModel
或2DModel
)。
我认为这是实现这一目标的唯一途径,这是对的吗?对于如此简单的事情,似乎有很多额外的代码。
编辑:
一些示例代码
public class View
{
}
public class 3DView : View
{
}
public class Model
{
public abstract View _view {get; set;}
}
public class 3DModel : Model
{
public override 3DView _view {get; set;}
}
我收到Visual Studio错误"重写属性时无法更改返回类型"。
您可以保留非泛型Model类,并引入一个抽象的泛型Model类。
public abstract class Model<TView> : Model where TView : View
{
public new TView _view
{
get { return base._view as TView; }
set { base._view = value; }
}
}
public class View3D : View { }
public class Model3D : Model<View3D> { }
public class View2D : View { }
public class Model2D : Model<View2D> { }
我认为这里有两种方法。
首先,您可以使用通常的继承:
public abstract class View
{
public abstract void Hello();
}
public class _3DView : View
{
public override void Hello()
{
Console.WriteLine("Hello from 3D View");
}
}
public class _2DView : View
{
public override void Hello()
{
Console.WriteLine("Hello from 2D View");
}
}
public abstract class Model
{
public abstract View { get; }
}
public _3DModel : Model
{
public override View { get { return new _3DView; } }
}
public _2DModel : Model
{
public override View { get { return new _2DView; } }
}
Model model = new _3DModel();
model.View.Hello(); // have "Hello from 3D View"
Model anotherModel = new _2DModel();
anotherModel.View.Hello(); // have "Hello from 2D View"
通过这种方式,您可以以多态方式处理模型和视图,并且仍然可以在需要时将View
强制转换为_3DView
。
或者你可以使用这样的泛型:
// Views are declared the same way
public abstract class Model<TView>
where TView: View
{
public abstract TView View { get; }
}
public class _3DModel : Model<_3DView>
{
public override _3DView View { get { return new _3DView; } }
}
public class _2DModel : Model<_2DView>
{
public override _2DView View { get { return new _2DView; } }
}
Model<_3DView> model = new _3DModel();
model.View.Hello();
泛型方法的缺点是你不能这样说:
Model model = new _3DModel();
因为没有单一的模型父级。在我看来,泛型方法在这种情况下毫无意义。
对我来说,最好的解决方案是使用泛型类。
你有另一个解决方案(更丑陋),就是为你的视图创建一个接口,并定义你的方法View()如下:
public IView View()
然后,您最终可以在2D/3D模型中创建特定属性:
public 2DView 2DView()
{
return this.View() as 2DView;
}
但是你不能得到与泛型类相同的结果。。。