【问题标题】:Partial classes/partial methods vs base/inherited classes部分类/部分方法与基类/继承类
【发布时间】:2010-01-13 11:59:28
【问题描述】:

关于班级设计的问题。目前我有以下结构:

抽象基础知识库类

默认存储库实现类(实现一些抽象方法,其中逻辑在所有特定类中是通用的,但其他类为空)

Specific Repository implementation Class(实现上述 Default 类中留空的部分)

我现在遇到的问题是,我在特定类中有一个特定的 Update() 方法,但是当这个方法中的所有代码执行时,也应该执行基类 Default 类中的一些代码。

我可以这样做

public override Update()
{
    // do Specific class actions and updates
    // ....

    // follow with base.Update()
    base.Update();
}

但这需要所有继承方法中的那些 base.XYZ() 调用。我可以用部分方法解决这个问题吗?

所以要求是在父类和继承类中都有代码(或者使用部分使这两个类成为一个类)并且应该执行来自两个地方的方法实现的代码。另外,如果我想把它转过来,先执行基类代码,然后执行继承的类代码呢?

谢谢

【问题讨论】:

  • Partials 用于扩展代码生成的类,除此之外我不会使用它们
  • 我无法完全理解您的意思。所以base.XYZ()base.Update() 必须被调用?但是XYZ()要在具体类中实现?
  • XYZ() 表示基本的 CRUD 操作插入、更新、删除......所以这些必须在具体类中实现,但重要的是要了解我有两个具体类:一个为业务提供默认实现逻辑,还有另一个(你可以认为它是 3 级类)提供了一些特殊的自定义实现。
  • 可能是一个问题有点难以理解。简单地说,我希望两个类中的实现合并,如果可能的话,应该即时执行,基类代码应该隐式执行(它应该来自类层次结构设计),而不是必须由基类调用。一些方法()
  • 如果您真正需要的是一个“附加模型”,其中基类方法将与其他方法一起自动触发:查看 EventHandler 模型。我认为部分类和/或方法与您在此处尝试实现的目标没有任何关系。

标签: c# .net inheritance partial-classes


【解决方案1】:

你有没有考虑过这样的事情:

public abstract class YourBaseClass
{
    public void Update()
    {
        // Do some stuff
        //

        // Invoke inherited class's  method
        UpdateCore();
    }

    protected abstract void UpdateCore();
}

public class YourChildClass : YourBaseClass
{
     protected override void UpdateCore()
     {
         //Do the important stuff
     }
}


//Somewhere else in code:
var ycc = new YourChildClass();
ycc.Update();

【讨论】:

  • 它是否是好的设计总是可以争论的。但它完成了工作,并在 .net 框架中被 MS 广泛使用。
【解决方案2】:

所有partial关键字的意思是类的定义在源文件之间分割:

可以将类或结构、接口或方法的定义拆分到两个或多个源文件中。每个源文件都包含一个类型或方法定义的部分,并且在编译应用程序时将所有部分组合在一起。

项目中的类还是要有完整的定义的。

你最好创建一个子类,这样你就可以覆盖特定的方法。

就部分方法而言(来自与上面相同的链接):

部分方法声明由两部分组成:定义和实现。它们可能位于部分类的不同部分中,也可能位于同一部分中。如果没有实现声明,则编译器会优化掉定义声明和对方法的所有调用。

// Definition in file1.cs
partial void onNameChanged();

// Implementation in file2.cs
partial void onNameChanged()
{
  // method body
}

你不能将一半的方法放在一个文件中,另一半放在另一个文件中。

【讨论】:

  • 我知道它被拆分为多个文件,但我不明白代码的执行顺序。也就是说,如果我们在两个文件中实现了一个部分方法的部分类,这两者如何结合在一起?
【解决方案3】:

您可以这样做:

public sealed override void Update()
{
    UpdateCore();
    base.Update();
}

public abstract /* or virtual */ void UpdateCore()
{
    // Class-specific stuff
}

【讨论】:

    【解决方案4】:

    忘记partial,它具有完全不同的语义。虚拟基类方法的覆盖器是否应该调用基类方法不是自动的。它需要成为您文档的一部分。一个很好的例子是 Control 类中的 OnXxxx() 方法,MSDN 库文档有一个“Note to implementer”注释,警告通常需要调用基类方法。

    如果您将基类方法设为抽象,那么覆盖器将非常清楚。如果不是,那么您正在强烈暗示应该这样做。如果您希望覆盖完全替换您的基本实现,那么您应该考虑将其抽象化。这种模棱两可,再加上覆盖器通过错误覆盖而破坏您的基类的可能性,绝对是多态性的弱点之一。

    【讨论】:

      【解决方案5】:

      向您的默认实现添加一个新的虚拟(不是抽象的,因为并非所有特定实现都需要覆盖它?)方法,以适应继承者在其自己的实现之上具有自己的附加步骤。

      在默认实现的抽象方法实现中的适当位置调用虚拟方法。

      您已将抽象类保持原样,并透明地增加了默认实现的灵活性。

      【讨论】:

        猜你喜欢
        • 2019-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-10
        • 1970-01-01
        • 2019-12-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多