[英]C# Abstract class has another abstract class object
I have few classes representing some measured data, at first ICut
abstract class with derived RoundCut
and SquareCut
like this: 我很少代表一些测量数据的类,起初,
ICut
抽象类具有派生的RoundCut
和SquareCut
如下所示:
public abstract class ICut
{
}
public class RoundCut : ICut
{
DoSomeWithRoundCut(){}
}
public class SquareCut : ICut
{
DoSomeWithSquareCut(){}
}
Of course it contains some implementation but it isn't important for this question. 当然,它包含一些实现,但是对于这个问题并不重要。
ICut
is abstract class instead of interface because it has some implemetation itself. ICut
是抽象类而不是接口,因为它本身具有一些实现。
Then, here are classes representing set of ICut
data, again base abstract IRoll
and derived RoundRoll
and SquareRoll
: 然后,这是代表
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;
}
}
And now, of course I'm not able to reach directly RoundCut
or SquareCut
extra implementation by calling for example: 而现在,我当然无法通过调用例如以下
SquareCut
直接达到RoundCut
或SquareCut
额外实现:
IRoll roll = new RoundRoll();
roll.CreateCut();
roll.cuts[0].DoSomeWithRoundRoll();
And I can't use neither: 而且我不能使用:
(roll.cuts[0] as RoundCut).DoSomeWithRoundRoll();
because I generally don't know if which IRoll
derivation roll
is. 因为我通常不知道哪个
IRoll
派生roll
是。
I'm refactoring huge project where all roll
objects were of type RoundRoll
and now the other has to be added. 我正在重构一个大型项目,其中所有
roll
对象均为RoundRoll
类型,现在必须添加其他对象。
Maybe I'm missing some kind of suitable design pattern, I'm in the begining of advanced OOP patterns learning curve, and I've been thinking about solution of this problem all the day. 也许我缺少某种合适的设计模式,正处于高级OOP模式学习曲线的开始,并且我一直在全天候在考虑解决此问题的方法。
UPDATE After many experiments, I realized that as a contrary to my primary opinions, I ended up with the solution of @The-First-Tiger with some improvements. 更新经过多次实验,我意识到与我的主要观点相反,我最终对@ The-First-Tiger的解决方案进行了一些改进。 I created simple factory:
我创建了简单的工厂:
// 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();
}
}
}
So I can create Cut like: 所以我可以像这样创建Cut:
ICut cut = CutFactory.GetCut(roll.GetShape());
And if needed to have different behavior: 并且如果需要具有不同的行为:
if (cut is RoundCut)
(cut as RoundCut).RoundCutSpecificMethod();
else if (cut is SquareCut)
(cut as SquareCut).SquareCutSpecificMethod();
One way to work around the problem is to make IRoll
generic on the type of its ICut
: 解决该问题的一种方法是使
IRoll
在其ICut
类型上ICut
:
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;
}
}
Now you can do this: 现在您可以执行以下操作:
public class RoundRoll : AbstractRoll<RoundCut> {
...
}
public class SquareRoll : AbstractRoll<SquareCut> {
...
}
Note that C# lets you move the boilerplate code to the base class by applying constraints to generic types. 请注意,C#使您可以通过将约束应用于泛型类型来将样板代码移动到基类。
The only remaining issue now is that AbstractRoll
is no longer a common interface for RoundRoll
and SquareRoll
, so you cannot create a collection of rolls. 现在唯一剩下的问题是
AbstractRoll
不再是RoundRoll
和SquareRoll
的通用接口,因此您无法创建纸卷集合。
This problem can be solved by adding a non-generic interface IRoll
on top of AbstractRoll
class, with the operations that are common to all rolls, and are also independent of the type of the roll's ICut
: 可以通过在
AbstractRoll
类的顶部添加非通用接口IRoll
来解决此问题,该接口具有所有卷所共有的操作,并且也与卷的ICut
类型ICut
:
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
}
You could rewrite your code using interfaces: 您可以使用以下接口重写代码:
public interface ICut
{
DoSomething();
}
public class RoundCut : ICut
{
DoSomething(){}
}
public class SquareCut : ICut
{
DoSomething(){}
}
public interface IRoll
{
IEnumerable<ICut> Cuts { get; };
ICut CreateCut();
}
public class RoundRoll : IRoll
{
public IEnumerable<ICut> Cuts { get; private set; }
public RoundRoll ()
{
this.Cuts = new List<ICut>();
}
public ICut CreateCut()
{
var cut = new RoundCut();
this.Cuts.Add(cut);
return cut;
}
}
public class SquareRoll : IRoll
{
public IEnumerable<ICut> Cuts { get; private set; }
public SquareRoll ()
{
this.Cuts = new List<ICut>();
}
public ICut CreateCut()
{
var cut = new SquareCut();
this.Cuts.Add(cut);
return cut;
}
}
IRoll roll = new RoundRoll();
var cut = roll.CreateCut();
cut.DoSomething();
If SquareCut and RoundCut have a lot of methods which are not common you can still check for ICuts concrete type and then cast to it: 如果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();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.