【问题标题】:How to combined similar-named nested classes from a derived and its base class如何组合派生类及其基类中命名相似的嵌套类
【发布时间】:2020-06-03 07:30:38
【问题描述】:

我正在从事一个小项目,我在该项目中为系统创建了附加组件的标准实现。这些标准实现将以统一的方式设置日志记录、配置等。所有这些都考虑到了可维护性和可重用性。

现在我正在努力解决的问题是如何处理设置名称。在我总是创建一个嵌套类 Settings 之前,我声明了一些 const 字符串值,例如

public const string BananaSetting = "BananaSetting";

所以我几乎再也不会拼错设置的名称了。

然而,我有一个基类,它应该有一个名为 DEBUG 的设置,用作通用调试启用设置;还有附加组件特定的设置,这些设置只存在于那个特定的附加组件中。 看到我将每个派生类都基于具有 DEBUG 设置嵌套类的类,任何试图声明类似嵌套类的派生类称为Settings 将触发编译器警告:

DerivedClass.Settings 隐藏继承的成员“BaseClass.Settings”。如果要隐藏,请使用 new 关键字。

但我不想隐藏它。我真正想做的是将两个设置类合二为一。有没有办法做到这一点,或者是否有某种现有的设计模式可以正确地做到这一点?

public abstract class BaseClass
{
    public class Settings
    {
        public const string BananaSetting = "BananaSetting";
    }

    public abstract void BaseAbstractMethod();
    public void BaseMethod()
    {
        // intended use
        var settingValue = settingsDictionary[Settings.BananaSetting];
    }
}

public class DerivedClass : BaseClass
{
    public class Settings
    {
        public const string DerivedBananaSetting = "DerivedBananaSetting";
    }

    public override void BaseAbstractMethod()
    {
        // intended use
        var settingValue = settingsDictionary[Settings.BananaSetting];
        var subSettingValue = settingsDictionary[Settings.DerivedBananaSetting];
    }
}

【问题讨论】:

  • 为更多说明向我们展示一些代码。
  • @HamedMoghadasi 我在代码中添加了基本思想(这会导致编译器警告)。

标签: c# .net inheritance


【解决方案1】:

您需要在派生类new 中创建设置类,因为它与基类中的名称相同。为了能够访问派生类中的基本设置,您还需要继承嵌套设置类:

public class DerivedClass : BaseClass
{
    public new class Settings : BaseClass.Settings
    {
        public const string DerivedBananaSetting = "DerivedBananaSetting";
    }
// etc..

你的代码的其余部分没有改变。

【讨论】:

  • 再次检查一下,如果我要创建另一个派生自 DerivedClass 的类,并再次执行该技巧,我仍然可以访问 BaseClass 的设置,对吧?
  • 是的,你会的。 DerivedClass.Settings 包含 BaseClass.Settings 的所有公共成员,如果您再次派生它们,它们就可以在层次结构中使用。
  • 完美,刚刚测试过它,它就像一个魅力。谢谢!
【解决方案2】:

怎么样。像这样:

public abstract class SettingBase
{
     public abstract string GetSettingName();

     public abstract SettingBase GetSetting();

     //Shared Properties and Stuff here:
}

public class BananaSetting : SettingBase
{
     public override string GetSettingName()
     {
         return nameof(BananaSetting);
     }

     public override SettingBase GetSetting()
     {
         return this;
     }

     //Banana-Specific Settings go here
}

public class DEBUGSetting : SettingBase
{
     public override string GetSettingName()
     {
         return nameof(DEBUGSetting);
     }

     public override SettingBase GetSetting()
     {
         return this;
     }

     //DEBUG-Specific Settings go here
}


public class Program
{
     public void Demo()
     {
         var settings = LoadSettings();
         foreach(var setting in settings)
         {
             var implementation = setting.GetSetting();
             if(implementation is DEBUGSetting dbg)
             {
                 //access dbg.Properties here
             }
             [...]
         }
     }
}

【讨论】:

  • 很有趣,但这会为每个设置创建一个类,这对于我有时可以在附加组件上拥有的 60 多个设置来说有点矫枉过正。另外,如果可能的话,我希望设置类被嵌套,因此它的常量专门指向该附加类型的设置。
【解决方案3】:

如果我理解正确,您想通过更多设置扩展基类:

public class SettingBase
{
     public SettingDerived()
     {
         _settingNamesWithValues.Add("BananaSetting", new object());
     }

    private Dictionairy<string, object> _settingNamesWithValues = new Dictionairy<string, object>();

    public Dictionairy<string, object>() SettingNamesWithValues
    {
         get
         { 
            return _settingNameWithValue;
         }
    }
}

派生类:

public class SettingDerived : SettingBase
{
     public SettingDerived()
     {
         _settingNamesWithValues.Add("DerivedBananaSetting", new object());
     }

     private Dictionairy<string, object> _settingNamesWithValues = new Dictionairy<string, object>(); 

     //Hide the base SettingNamesWithValues, as we add the values to the derived collection anyways
     public new Dictionairy<string, object>() SettingNamesWithValues
     {
         get
         { 
            foreach(var keyValue in base.SettingNamesWithValues)
            {
                 _settingNameWithValue.Add(keyValue.Key, keyValue.Value);
            }                  
            return _settingNameWithValue;
         }
     }
}

然后您可以使用他们的名字访问所有设置。

var derived = new SettingsDerived();
var derivedBanana = derived.SettingNamesWithValues["DerivedBananaSetting"];
var banana = derived.SettingNamesWithValues["BananaSetting"];

【讨论】:

  • 带有设置的字典来自我工作的框架,因此它已经允许我检索这样的设置。我想要完成的是使它不会拼错设置的名称,因为我在各自的 Settings 类中将它们作为 const 字符串。
【解决方案4】:

是否需要将它们放在子类中?您可以通过以下方式轻松实现目标:

public abstract class BaseClass
{
    public const string BananaSetting = "BananaSetting";

    public abstract void BaseAbstractMethod();
    public void BaseMethod()
    {
    }
}

public class DerivedClass : BaseClass
{
    public const string DerivedBananaSetting = "DerivedBananaSetting";

    public override void BaseAbstractMethod()
    {
    }
}

【讨论】:

  • 我将它们放在嵌套类中的唯一原因是为了分组和可读性。我最初有这样的设置,但我无法通过查看代码轻松发现我使用设置的位置(是的,我有点强迫症),发现 Settings.BananaSetting 更容易,因为我猜想是颜色类名称。
  • 可以理解,我已将 iakobski 的答案标记为有用,因为他的答案作为解决方案更加完整和清晰。我将把我的留在这里作为“另一种方法”
猜你喜欢
  • 1970-01-01
  • 2018-12-08
  • 2016-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-09
  • 1970-01-01
  • 2022-01-19
相关资源
最近更新 更多