【问题标题】:The best way to use child classes and methods使用子类和方法的最佳方式
【发布时间】:2015-02-04 21:06:35
【问题描述】:

有一些新手问题。 我有 6 节课:

public class MainSettingsClass
{
    int a;
    int b;
}

public class SubSettingsClass_1 : MainSettingsClass
{
    int c;
}

public class SubSettingsClass_2 : MainSettingsClass
{
    int d;
}

public class ParentClass
{
    public MainSettingsClass settings;
}

public class ChildClass_1 : ParentClass
{
}

public class ChildClass_2 : ParentClass
{
}

现在是问题。 ChildClass_1 和 SubSettingsClass_1 和 ChildClass_2 和 SubSettingsClass_1

ChildClass_1 firstClassVar = new ChildClass_1();
ChildClass_2 secondClassVar = new ChildClass_2();
SubSettingsClass_1 firstClassSettings = new SubSettingsClass_1();
SubSettingsClass_2 secondClassSettings = new SubSettingsClass_2();
firstClassVar.settings = (MainSettingsClass)firstClassSettings;
secondClassVar.settings = (MainSettingsClass)secondClassSettings;

如果我需要使用“firstClassVar.settings”获取“c”变量,我需要每次写入:

 ((firstClassSettings)firstClassVar.settings).c
  1. 访问变量的方法是否正确?
  2. 还是有更好的方法存在?
  3. 这段代码是否符合编程规则?还是不正确?

抱歉英语不好。

【问题讨论】:

    标签: c# class coding-style


    【解决方案1】:
    1. 这是访问c 变量的“正确”方式吗? 。如果你要失望,至少先检查一下:

      firstClassSettings derivedSettings = firstClassVar.settings as firstClassSettings;
      if (derivedSettings != nulL)
      {
          //Do whatever with derivedSettings.c
      }
      
    2. 有一个更好的方法:) 它叫做多态。您的类是超级通用的,因此很难准确地说明您的设计应该是什么样子,但是您的主类应该有一些方法,派生类会覆盖这些方法以获得自定义行为。

      李>
    3. 向下转换是一种巨大的代码气味。有时无法绕过它(尤其是在遗留代码中,或在某些 Object 覆盖和 WPF 接口中),但是,如果可能的话,您应该避免它。在您自己的对象/代码中更是如此。

    【讨论】:

    • 是否可以改变变量的类型?例如: public class ChildClass_1 : ParentClass { public SubSettingsClass_1 settings;例如我有循环。我不知道循环中将使用什么对象 Child_1 或 Child_2,但每次我需要获取它们的(共享、“a”或“b”)设置类变量。 Child_1 对象只有 Subsettings_1,Child_2 只有 Subsettings_2。在这种情况下如何在循环中访问变量“a”?
    • @denismart 按原样使用它:)。该变量已经是MainSettingsClass 类型,因此您可以安全地编写settings.aUpcasting 很常见,也很安全。你必须小心它的垂头丧气。
    【解决方案2】:

    您所拥有的技术上很好,尽管有一些问题。首先,无需转换为MainSettingsClass。由于SubSettingsClass_1SubSettingsClass_2 都继承自MainSettingsClassParentClass 及其所有派生类,因此将接受其中任何一个作为定义为MainSettingsClass 类型的字段的值。

    其次,字段(settings 是其中之一)通常不会公开。定义了 getter 和 setter 的属性通常是对象数据的接口。

    第三,settings 这里是一个依赖,因此,应该通过类的构造函数真正注入。比如:

    public class ParentClass
    {
        protected MainSettingsClass settings;
    
        public ParentClass(MainSettingsClass settings)
        {
            this.settings = settings;
        }
    }
    

    更新

    我刚刚想到的另一件事对您有所帮助。请记住,通过使用像MainSettingsClass 这样的最小公分母,您将无法使用更具体的派生类SubSettingsClass_1SubSettingsClass_2 的特定成员。然而,泛型可以用来给你更多的灵活性:

    public class ParentClass<TSettings>
        where TSettings : MainSettingsClass
    {
        protected TSettings settings;
    
        public ParentClass(TSettings settings)
        {
            this.settings = settings;
        }
    }
    
    public class ChildClass_1 : ParentClass<SubSettingsClass_1>
    {
        ...
    }
    
    public class ChildClass_2 : ParentClass<SubSettingsClass_2>
    {
        ...
    }
    

    这样,您现在可以在ChildClass_1 中使用c 和在ChildClass_2 中使用d,因为您的settings 字段的类型将分别为SubSettingsClass_1SubSettingsClass_2

    【讨论】:

    • 感谢您在我忘记谈论的代码中发现了所有糟糕的做法。 +1
    • 谢谢,这也很有用!
    猜你喜欢
    • 2011-05-26
    • 1970-01-01
    • 2017-08-01
    • 2015-04-30
    • 2019-03-28
    • 2013-04-11
    • 2012-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多