在子方法中不使用关键字new显式使用基本方法

时间:2015-12-02 09:44:08

标签: c# .net oop inheritance polymorphism

由于类的多态属性,下面的示例将打印AB两次,这是预期的。

在我的情况下,我真的希望它打印A然后AB

我决定将Get()中的B方法从overrides更改为new。 这解决了我的问题,但他们告诉我不好的做法,所以我正在寻找替代方案...

我想到的一件事是instantiate a new A in B.Do(),我认为这也是不好的做法......

//ORIGINAL
class Program
{
    static void Main(string[] args)
    {
        var b = new B();
        b.Do();
    }
}

public class A
{
    public virtual void Do()
    {
        var get = Get();
        Console.WriteLine(get);
    }

    public virtual string Get()
    {
        return "A";
    }
}

public class B : A
{
    public override void Do()
    {
        base.Do();

        var get = Get();
        Console.WriteLine(get);
    }

    public override string Get()
    {
        return base.Get() + "B";
    }
}

//UPDATED, USING NEW
class Program
{
    static void Main(string[] args)
    {
        var b = new B();
        b.Do();

        Console.ReadLine();
    }
}

public class A
{
    public virtual void Do()
    {
        var get = Get();
        Console.WriteLine(get);
    }

    public virtual string Get()
    {
        return "A";
    }
}

public class B : A
{
    public override void Do()
    {
        base.Do();

        var get = Get();
        Console.WriteLine(get);
    }

    public new string Get()
    {
        return base.Get() + "B";
    }
}

2 个答案:

答案 0 :(得分:0)

您可以按以下方式更改实施,而不是在Do中调用B.Do的基本版本:

public class B : A
{
  public override void Do()
  {
    // Call the base version of Get explicitly
    var getBase = base.Get();
    Console.WriteLine(getBase);
    // Call the current implementation of Get
    var get = Get();
    Console.WriteLine(get);
  }

  public override string Get()
  {
    return "B";
  }
}

这将在技术上解决您的问题,但从OOP的角度来看,这不是一个非常干净的解决方案。我建议您考虑是否需要能够独立覆盖Get。也许更改方法的签名以便Get始终返回应打印的字符串列表也是一个很好的解决方案(我已将Get重命名为GetLines以反映更改后的目的方法):

public class A
{
    public virtual void Do()
    {
        var lines = GetLines();
        foreach(var line in lines)
            Console.WriteLine(line);
    }

    public virtual IEnumerable<string> GetLines()
    {
        return new string[] { "A" };
    }
}

public class B : A
{

    public override IEnumerable<string> GetLines()
    {
        var lst = new List<string>(base.GetLines());
        lst.Add("B");
        return lst;
    }
}

答案 1 :(得分:0)

以下是更正后的代码:

class Program
{
    static void Main(string[] args)
    {
        var b = new B();
        b.Do();
    }
}

public class A
{
    public virtual void Do()
    {
        Console.WriteLine(Get());
    }

    public virtual string Get()
    {
        return "A";
    }
}

public class B : A
{
    public override void Do()
    {
        Console.WriteLine(base.Get());
        base.Do();
    }

    public override string Get()
    {
        return base.Get() + "B";
    }
}