【问题标题】:How to modify method return value in all derived classes?如何修改所有派生类中的方法返回值?
【发布时间】:2014-11-25 14:58:04
【问题描述】:

假设您有一个类层次结构:

class Base
{
    public virtual string GetName()
    {
        return "BaseName";
    }
}

class Derived1 : Base
{
    public override string GetName()
    {
        return "Derived1";
    }
}

class Derived2 : Base
{
    public override string GetName()
    {
        return "Derived2";
    }
}

如何以最合适的方式编写代码,使所有“GetName”方法都在派生类中添加“XX”字符串以返回值?

例如:

         Derived1.GetName returns "Derived1XX"

         Derived2.GetName returns "Derived2XX"

更改GetName方法实现的代码不是好主意,因为Base可能存在几种派生类型。

【问题讨论】:

  • 这通常不是一个好的设计。如果您不希望孩子们发生某些变化,请发送sealed
  • @Renan 方法默认是密封的,它们必须是 virtual 才能被覆盖。如果班级是sealed,则不能有孩子。并且 OP 确实希望 GetName 在每个孩子中返回不同的东西——他只想要一个共同的后缀。
  • @Blorgbeard true.dat。我完全忘记了。
  • @Renan 其实我只是noticed 说你可以在你覆盖它们时实际上密封方法,这样它们就不能被进一步覆盖。但它只允许覆盖虚拟方法。

标签: c# .net oop design-patterns


【解决方案1】:

覆盖可以调用它的基函数...然后您可以修改基类以在其中附加您想要的字符。

【讨论】:

    【解决方案2】:

    如果您不想(或不能)修改原始类,可以使用扩展方法:

    static class Exts {
        public static string GetNameXX (this Base @this) {
            return @this.GetName() + "XX";
        }
    }
    

    您将能够像往常一样访问新方法:

    new Derived1().GetNameXX();
    

    【讨论】:

      【解决方案3】:

      GetName 保留为非虚拟,并将“追加XX”逻辑放入该函数中。将名称(不带“XX”)提取到受保护的虚函数,并在子类中覆盖它。

      class Base
      {
          public string GetName()
          {
              return GetNameInternal() + "XX";
          }
      
          protected virtual string GetNameInternal() 
          {
              return "BaseName";
          }
      }
      
      class Derived1 : Base
      {
          protected override string GetNameInternal()
          {
              return "Derived1";
          }
      }
      
      class Derived2 : Base
      {
          protected override string GetNameInternal()
          {
              return "Derived2";
          }
      }
      

      【讨论】:

        【解决方案4】:

        这是装饰器模式的一个很好的用例。创建一个引用 Base 的装饰器:

        class BaseDecorator : Base
        {
            Base _baseType;
        
            public BaseDecorator(Base baseType)
            {
                _baseType = baseType;
            {
        
            public override string GetName()
            {
                return _baseType.GetName() + "XX";
            }
        }
        

        使用您选择的类(Base 或 Derived)构造一个 BaseDecorator,并在其上调用 GetName。

        【讨论】:

        • 这似乎是一个很好的解决方案。可以应用的另一种模式是Strategy Pattern
        【解决方案5】:

        您可以将名称的构造拆分为多个可覆盖的部分,然后在每个不同的子类中覆盖每个部分。 下面是一个这样的例子。

        public class Base {
          public string GetName() {
            return GetPrefix() + GetSuffix();
          }
          protected virtual string GetPrefix() {
            return "Base";
          }
          protected virtual string GetSuffix() {
            return "";
          }
        }
        
        public class DerivedConstantSuffix : Base {
          protected override string GetSuffix() {
            return "XX";
          }
        }
        
        public class Derived1 : DerivedConstantSuffix {
          protected override string GetPrefix() {
            return "Derived1";
          }
        }
        
        public class Derived2 : DerivedConstantSuffix {
          protected override string GetPrefix() {
            return "Derived2";
          }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-06-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-01-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多