构造函数中的抽象类型而不是Concrete类型

时间:2013-08-20 14:35:28

标签: c# .net polymorphism abstract-class

我有一个对象,假设是后来返回给客户端的数据 他们称之为网络方法。

        // NewData1.cs
        public NewData1(Concrete1 con)
        {
            ID = con.ID;
            var results= con.listOfResults();

                var something= con.GetSomething();
                Something = new List<Somethings>();

                con.DoSomething();
            }

            // NewData2.cs
            public NewData2(Concrete2 con)
            {
                ID = con.ID;
                var results= con.listOfResults();

                var something= con.GetSomething();
                Something = new List<Somethings>();

                con.DoSomething();
            }

            // NewData3.cs
            public NewData3(Concrete3 con)
            {
                ID = con.ID;
                var results= con.listOfResults();

                var something= con.GetSomething();
                Something = new List<Somethings>();

                con.DoSomething();
            }

正如你可以看到那些类做同样的事情(它不是我的代码......我想改变它)。 唯一不同的是具体类型(1,2,3)在调用方法时执行不同的逻辑。

你知道一种方法可以将这些类减少到一个类但仍然使它们的特殊逻辑不同吗?

4 个答案:

答案 0 :(得分:1)

如果您的Concrete1Concrete2Concrete3类共享相同的方法,则可以将其解压缩为界面并让它们实现:

// an interface is simply a contract
interface ICanGetSomething
{
    int ID { get; }
    List<Result> ListOfResults();
    Something GetSomething();
}

// your concrete classes should all implement the same interface
class Concrete1 : ICanGetSomething { ... }
class Concrete2 : ICanGetSomething { ... }
class Concrete3 : ICanGetSomething { ... }

这样你只需要一个方法来处理所有这些:

public void NewData(ICanGetSomething con)
{
    ID = con.ID;
    var results = con.ListOfResults();
    var something = con.GetSomething();
    ...
}

如果它们也共享相同的功能,您还可以使用公共抽象类来重用所有公共代码:

abstract class Base : ICanGetSomething { ... }

// your concrete classes should all inherit from the same base class
class Concrete1 : Base { ... }
class Concrete2 : Base { ... }
class Concrete3 : Base { ... }

无论哪种方式,我建议使用接口来定义合同。由于C#不支持多继承,因此您不希望强制所有具体实现派生自单个基类(除非必要)。这仍然意味着您将在具有共享功能的地方使用继承,但您的NewData方法应该接受参数的接口,而不是基类。

答案 1 :(得分:0)

您需要一个抽象基类:

public abstract class BaseClass
{
    // Use protected fields to store data that only this class and derived
    // classes can access.
    protected List<Something> storedSomethings;

    //Define an abstract method signature for methods that the concrete classes
    // have very different implementations for:
    public abstract List<Something>GetSomethings();

    //Use a virtual method for methods that are identical or similar on 
    //the concrete classes:
    public virtual void AddSomethings(List<Something> addList)
    {
        storedSomethings.Add(addList);
    }
}

然后你的具体类就像这样实现:

public class Concrete1 : BaseClass
{

    public override List<Something> GetSomethings()
    {
    //actual logic here
    }

    //override any other abstract methods
}

public class Concrete2 : BaseClass
{

    public override List<Something> GetSomethings()
    {
    //actual logic here
    }

    //override any other abstract methods
}

Concrete3稍有不同,需要对addomethings进行过滤:

public class Concrete3 : BaseClass
{

    public override List<Something> GetSomethings()
    {
    //actual logic here
    }

    //override any other abstract methods

    //For some reason this class doesn't want all somethings, so it overrides
    // the base method and filters before calling the base method
    public override AddSomethings(List<Something> addList)
    {
        base.AddSomethings(addList.Where(s => s.Condition == false));
    }
}

现在,您只需要一个新的数据类:

public newdata(BaseClass classInstance)
{
    //As long as every method you want to call is defined on BaseClass
    // and implemented on the concrete classes, you can just do:
    classInstance.GetSomething();
}

答案 2 :(得分:0)

创建以下基类。

public class Concrete
{
    public int ID { get; set; }

    public virtual something GetSomething()
    {

    }

    public virtual void DoSomething()
    {

    }
}

你的concrete1,concrete2等类扩展了Concrete。如果需要,这些类将能够覆盖GetSomething方法。 那么你只需要其中一个。

public NewData2(Concrete con)
{
    ID = con.ID;
    var results= con.listOfResults();

    var something= con.GetSomething();
    Something = new List<Somethings>();

    con.DoSomething();
}

答案 3 :(得分:0)

如果所有3个派生类具有完全相同的签名,则可以从Concrete创建抽象基类。

基类:

public abstract class AbstractBaseClass
{
    public long ID { get; set; }
    public abstract List<string> ListOfResults();
    public abstract string GetSomething();
    public abstract void DoSomething();
}

你的具体来自它:

public class Concrete1 : AbstractBaseClass
{
    public override List<string> ListOfResults()
    {
        // Logic
    }

    public override string GetSomething()
    {
        // Logic
    }

    public override void DoSomething()
    {
        // Logic
    }
}

将参数设置为基类:

public void NewData(AbstractBaseClass abs)
{
    ID = abs.ID;

    var results= abs.listOfResults();
    var something= abs.GetSomething();
    abs.DoSomething();
}

您现在可以这样做,例如:

NewData data = new NewData(new Concrete1());

NewData构造函数中的所有调用都将定向到Concrete1子类。

如果只能有一个NewData实例,则可以在需要时使用Stategy Pattern更改具体类。