在重载方法中调用基类的抽象方法

5
如果我有以下内容:
例如。
public abstract class ClassA
{
     protected abstract void ValidateTransaction();
}

public abstract class ClassB : ClassA
{
     protected override void ValidateTransaction()
     {
          // some custom logic here
     }
}

public class ClassC : ClassB
{
     protected override void ValidateTransaction()
     {
          base.ValidateTransaction();
          // some additional custom logic here
     }
}

所以,我在ClassC的ValidateTransaction上没有找到用法。我没有看到它被调用过。

那么我猜这个是怎么工作的呢?我的意思是,它在这里调用了堆栈顶部的方法(调用ClassB的重写方法,然后在ClassC的重写方法中包含逻辑?)

这对我来说没有道理,为什么或者如何工作,或者这里的意图。

更新

好的,我找到了一个地方,在我们项目的许多子类中都调用了ClassA的PerformTransaction()方法。

因此,现在ClassA看起来像这样,并为您提供更多详细信息:

public abstract class ClassA
{
     public void PerformTransaction()
     {
           ValidateTransaction();
           // and calls some other code here.
     }

     protected abstract void ValidateTransaction();
}
好的,那么我们还有以下内容:
public abstract class ClassB : ClassA
{
     protected override void ValidateTransaction()
     {
          // some custom logic here
     }
}

public class ClassC : ClassB
{
     protected override void ValidateTransaction()
     {
          base.ValidateTransaction();
          // some additional custom logic here
     }
}


public class SomeAbritraryClass : ClassC
{
      ClassA.PerformTransaction();
      ...
 }

在一些继承ClassC的类中调用了ClassA.PerformTransaction()。

3个回答

2
好的,它调用了ClassC的重写方法...这个方法恰好调用了ClassB的实现。它并没有直接在ClassC的编译代码中“包含”ClassB的实现逻辑或其他任何内容 - 它只是另一个方法调用。
不清楚什么让你感到困惑 - 是行为、设计意图还是Find Usages正在显示的内容。
请注意,尽管您的主题行是这样的,但您并没有调用“基础抽象方法” - 您调用的是该方法的实现。编译器知道ClassC派生自ClassB,后者提供了该方法的实现,因此它明确地进行了调用。您无法从ClassB本身执行相同的操作,因为那么base.ValidateTransaction真正将尝试调用一个抽象基方法。
有趣的事实:尽管这是一种虚拟方法调用,但它是一种非虚拟方法调用:编译器知道要使用的确切实现,并将其编入调用中。如果这是一个虚拟调用,您最终会回到ClassC的实现中,因为它覆盖了它 :)

抱歉约翰,我在我的帖子中搞砸了。我没有找到使用ClassC的实例。让我更正我的原始帖子。 - PositiveGuy
1
@CoffeeAddict: 但是是“查找用法”让您感到困惑吗?请注意,ClassC.ValidateTransaction仍然可以像这样被调用:ClassA x = new ClassC(); a.ValidateTransaction(); - Jon Skeet
啊...没有考虑到那一点。然而,再次查看代码...我发现现在我仔细观察后调用该方法的唯一位置是在基类中。它调用我原始抽象类中定义的那个抽象子类。因此ClassA中有一些方法调用ValidateTransaction()。这必须会向下传递吧? - PositiveGuy
是的,没错。这就是为什么我感到困惑。让我再看看代码,然后回来。这毫无意义。我不确定方法是如何被调用的...是否正确。我需要重写并添加自定义逻辑到那个方法中。我正在模仿过去的做法。所以在ClassC的覆盖方法中,他们首先调用了base.ValidateTransaction(),然后在其后添加了额外的自定义逻辑,正如你所看到的。但是如果ClassC的方法没有被调用,我不知道这是如何工作的... - PositiveGuy
@CoffeeAddict:与其一点一点地更新,我强烈建议您尝试提取一小段完整的代码,以便我们可以复制、粘贴、编译和运行。这样我们就会知道没有任何“额外”的操作。 - Jon Skeet
显示剩余3条评论

0
那么这是如何工作的呢?我的意思是在这里调用了堆栈顶部的方法(调用ClassB的重写方法,然后在ClassC的ClassB方法重写中包含逻辑?)
是的,基本上就是这样。当您在ClassC实例上调用ValidateTransaction时,它的方法会运行。然后,它明确地执行基类(ClassB)方法,然后添加自己的额外验证。
您可能没有找到ClassB.ValidateTransaction()的直接用法,因为没有定义为ClassB的实例(定义为ClassB)调用它。但是,任何ClassC调用都将通过base.ValidateTransaction()行间接使用ClassB.ValidateTransaction()。

抱歉,我没有找到 ClassC 的使用实例。让我更正一下我的原始帖子。 - PositiveGuy

0

当调用C类覆盖时,它将首先调用B的覆盖并在那里执行一些逻辑,然后由C的逻辑扩展。

据我所知,他们可能正在使用相同的变量和数据。我不知道,因为我没有所有的数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接