C#抽象类有另一个抽象类对象
我有几个类表示一些测量数据,首先是带有派生的C#抽象类有另一个抽象类对象,c#,oop,inheritance,abstract,C#,Oop,Inheritance,Abstract,我有几个类表示一些测量数据,首先是带有派生的RoundCut和SquareCut的ICut抽象类,如下所示: public abstract class ICut { } public class RoundCut : ICut { DoSomeWithRoundCut(){} } public class SquareCut : ICut { DoSomeWithSquareCut(){} } 当然,它包含一些实现,但对于这个问题来说并不重要ICut是抽象类而不是接口,因
RoundCut
和SquareCut
的ICut
抽象类,如下所示:
public abstract class ICut
{
}
public class RoundCut : ICut
{
DoSomeWithRoundCut(){}
}
public class SquareCut : ICut
{
DoSomeWithSquareCut(){}
}
当然,它包含一些实现,但对于这个问题来说并不重要ICut
是抽象类而不是接口,因为它本身有一些实现
然后,这里是表示ICut
数据集的类,同样是基于抽象IRoll
和派生RoundRoll
和SquareRoll
:
public abstract class IRoll
{
// list of measured cuts
public List<ICut> cuts;
// Create new cut
public abstract ICut CreateCut();
}
public class RoundRoll : IRoll
{
public RoundRoll ()
{
cuts = new List<RoundCut>();
}
public override ICut CreateCut()
{
RoundCut cut = new RoundCut();
cuts.Add(cut);
return cut;
}
}
public class SquareRoll : IRoll
{
public SquareRoll()
{
cuts = new List<SquareCut>();
}
public override ICut CreateCut()
{
SquareCut cut = new SquareCut();
cuts.Add(cut);
return cut;
}
}
我两个都不能用:
(roll.cuts[0] as RoundCut).DoSomeWithRoundRoll();
因为我通常不知道哪个IRoll
派生roll
是
我正在重构一个巨大的项目,其中所有roll
对象都是RoundRoll
类型,现在必须添加另一个
也许我缺少了某种合适的设计模式,我正处于高级OOP模式学习曲线的开始阶段,我整天都在思考这个问题的解决方案
更新
经过多次实验,我意识到,与我最初的观点相反,我最终得到了“第一只老虎”的解决方案,并进行了一些改进。我创建了简单工厂:
// Cut factory
public static class CutFactory
{
// Get new cut by given shape type
public static ICut GetCut(RollShape shape)
{
switch (shape)
{
case RollShape.Round:
return new RoundCut();
case RollShape.Square:
return new SquareCut();
default:
throw new ArgumentException();
}
}
}
因此,我可以创建如下剪切:
ICut cut = CutFactory.GetCut(roll.GetShape());
如果需要有不同的行为:
if (cut is RoundCut)
(cut as RoundCut).RoundCutSpecificMethod();
else if (cut is SquareCut)
(cut as SquareCut).SquareCutSpecificMethod();
解决此问题的一种方法是对其
ICut
的类型进行IRoll
通用化:
public abstract class AbstractRoll<T> where T : ICut, new {
// list of measured cuts
public List<T> cuts = new List<T>();
// Create new cut
public T CreateCut() {
var res = new T();
curs.Add(res);
return res;
}
}
public interface IRoll {
IEnumerable<ICut> Cuts { get; }
... // add other useful methods here
}
public abstract class AbstractRoll<T> : IRoll where T : ICut, new {
...
public IEnumerable<ICut> Cuts {
get {
return curs.Cast<ICut>();
}
}
... // implement other useful methods here
}
解决此问题的一种方法是对其
ICut
的类型进行IRoll
通用化:
public abstract class AbstractRoll<T> where T : ICut, new {
// list of measured cuts
public List<T> cuts = new List<T>();
// Create new cut
public T CreateCut() {
var res = new T();
curs.Add(res);
return res;
}
}
public interface IRoll {
IEnumerable<ICut> Cuts { get; }
... // add other useful methods here
}
public abstract class AbstractRoll<T> : IRoll where T : ICut, new {
...
public IEnumerable<ICut> Cuts {
get {
return curs.Cast<ICut>();
}
}
... // implement other useful methods here
}
您可以使用以下接口重写代码:
public interface ICut
{
DoSomething();
}
public class RoundCut : ICut
{
DoSomething(){}
}
public class SquareCut : ICut
{
DoSomething(){}
}
更新 如果SquareCut和RoundCut有很多不常见的方法,您仍然可以检查ICuts混凝土类型,然后进行浇筑:
IRoll roll = new RoundRoll();
var cut = roll.CreateCut();
if (cut is RoundCut) {
(cut as RoundCut).RoundCutSpecificMethod();
}
else if (cut is SquareCut) {
(cut as SquareCut).SquareCutSpecificMethod();
}
您可以使用以下接口重写代码:
public interface ICut
{
DoSomething();
}
public class RoundCut : ICut
{
DoSomething(){}
}
public class SquareCut : ICut
{
DoSomething(){}
}
更新 如果SquareCut和RoundCut有很多不常见的方法,您仍然可以检查ICuts混凝土类型,然后进行浇筑:
IRoll roll = new RoundRoll();
var cut = roll.CreateCut();
if (cut is RoundCut) {
(cut as RoundCut).RoundCutSpecificMethod();
}
else if (cut is SquareCut) {
(cut as SquareCut).SquareCutSpecificMethod();
}
为什么不在抽象类中简单地放一个抽象DoSomething方法,这样无论它是什么具体类型都可以调用它呢?我想还有一件事是接口的约定,而不是抽象类。你们考虑过使用泛型吗?例如,您可以使
IRoll
界面像IRoll一样通用,其中TCut:ICut
cuts=newlist()代码>和cuts=新列表()
也不应该编译。有几个问题,帮你自己一个忙——在YouTube上查找“bob solid叔叔”。你的命名对于C#标准来说有点奇怪。接口是唯一以I
为前缀的东西,抽象类通常不会得到前缀。为什么不在抽象类中简单地放一个抽象DoSomething方法,这样无论它是什么具体类型都可以调用它呢?我想还有一件事是接口的约定,而不是抽象类。你们考虑过使用泛型吗?例如,您可以使IRoll
界面像IRoll一样通用,其中TCut:ICut
cuts=newlist()代码>和cuts=新列表()
也不应该编译。有几个问题,帮你自己一个忙——在YouTube上查找“bob solid叔叔”。你的命名对于C#标准来说有点奇怪。接口是唯一以I
为前缀的对象,抽象类通常不会得到前缀。不幸的是,我还需要在IRoll
中保留一些数据成员,因此我需要使用抽象类来实现此目的。您仍然可以在抽象类中放置DoSomething方法,而不是派生方法?否则,您可以使用(roll.cuts[0]是RoundCut)->强制转换为RoundCutOk来测试我的理解。问题是,圆切和方切的剂量测量不常见。每一个衍生物都包含许多方法。至少有一些共同点,我已经按照你的建议尝试移动到ICut。谢谢更新。我需要检查类型并根据我的逻辑强制转换IRoll对象。按照您的代码,我还需要检查ICut类型,并在每次需要acces切割时将其转换为混凝土类型。在这种情况下,它会起作用,但需要付出巨大的努力。我想,使用泛型的解决方案更容易解决这个问题。不幸的是,我还需要在IRoll
中保留一些数据成员,因此我需要使用抽象类来解决这个问题。您仍然可以在抽象类中放置DoSomething方法,而不是派生方法?否则,您可以使用(roll.cuts[0]是RoundCut)->强制转换为RoundCutOk来测试我的理解。问题是,圆切和方切的剂量测量不常见。每一个衍生物都包含许多方法。至少有一些共同点,我已经按照你的建议尝试移动到ICut。谢谢更新。我需要检查类型并根据我的逻辑强制转换IRoll对象。按照您的代码,我还需要检查ICut类型,并在每次需要acces切割时将其转换为混凝土类型。在这种情况下,它会起作用,但需要付出巨大的努力。我想使用泛型的解决方案会更容易解决这个问题。这很有意义,泛型可以解决我的问题。谢谢我将尝试遵循这个模式。现在,我当然不能使用IRoll-roll代码>实例,也不能使用IRoll滚动代码>因为它不是ICut
的实现。但是当我需要使用泛型IRoll
对象时,如何使用它呢?Thanks@Majak这就是我在回答的第二部分试图解决的问题。我将IRoll
重命名为AbstractRoll
,并添加了一些示例代码来说明我的意思。这很有意义,generic可以解决我的问题。谢谢我将尝试遵循这个模式。现在,我当然不能使用IRoll-roll代码>实例,也不能使用IRoll滚动代码>因为它不是ICut
的实现。但是当我需要使用泛型IRoll
对象时,如何使用它呢?Thanks@Majak这就是我在回答的第二部分试图解决的问题。我将IRoll
重命名为