Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#抽象类有另一个抽象类对象_C#_Oop_Inheritance_Abstract - Fatal编程技术网

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
重命名为