【问题标题】:Explicit use of base method without using keyword new in child method在子方法中显式使用基本方法而不使用关键字 new
【发布时间】:2016-03-06 11:59:07
【问题描述】:

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

就我而言,我真的希望它先打印A,然后再打印AB

我决定将B 中的Get() 方法从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";
    }
}

【问题讨论】:

  • 不是重复的,而是对我认为您正在寻找的功能的引用:MyClass equivalent in C#
  • @Damien_The_Unbeliever 这也可能是我的问题的解决方案。谢谢你,我会读进去的。

标签: c# .net oop inheritance polymorphism


【解决方案1】:

除了在B.Do 中调用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;
    }
}

【讨论】:

    【解决方案2】:

    以下是更正后的代码:

    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";
        }
    }
    

    【讨论】:

    • 感谢您的回答,但您所做的是 B.Get() 上的隐含新功能。 Visual Studio 甚至用波浪线标记了这一点,并告诉我我需要实现新的。
    • 你说的完全正确,我错过了那部分。抱歉 :) 我也稍微更新了我的问题,因为 B.Get() 也调用 base.Get(),因此我无法使用您的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 2020-10-11
    • 1970-01-01
    • 2017-02-26
    • 2017-01-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多