非虚拟和抽象方法的命名约定

时间:2010-04-08 04:19:47

标签: language-agnostic design-patterns oop naming-conventions

我经常发现自己正在创建使用此表单的类(A):

abstract class Animal {
  public void Walk() {
    // TODO: do something before walking

    // custom logic implemented by each subclass
    WalkInternal();

    // TODO: do something after walking
  }
  protected abstract void WalkInternal();
}

class Dog : Animal {
  protected override void WalkInternal() {
    // TODO: walk with 4 legs
  }
}

class Bird : Animal {
  protected override void WalkInternal() {
    // TODO: walk with 2 legs
  }
}

而不是这种形式(B):

abstract class Animal {
  public abstract void Walk();
}

class Dog : Animal {
  public override void Walk() {
    // TODO: do something before walking

    // custom logic implemented by each subclass
    // TODO: walk with 4 legs

    // TODO: do something after walking
  }
}

class Bird : Animal {
  public override void Walk() {
    // TODO: do something before walking

    // custom logic implemented by each subclass
    // TODO: walk with 2 legs

    // TODO: do something after walking
  }
}

正如您所看到的,表单A的优点在于,每次实现子类时,都不需要记住包含初始化和终结逻辑。这比B形式更不容易出错。

命名这些方法的标准惯例是什么?
我喜欢命名公共方法Walk,因为那时我可以调用Dog.Walk(),它看起来比Dog.WalkExternal()更好。但是,我不喜欢我为受保护方法添加后缀“Internal”的解决方案。我正在寻找一个更标准化的名字。

顺便问一下,这个设计模式有名字吗?

8 个答案:

答案 0 :(得分:11)

我不确定是否有标准的命名约定。除WalkInternal外,其他替代方案可能是DoWalkWalkImpl

答案 1 :(得分:10)

  

顺便问一下,这个设计模式有名字吗?

您的第一个示例使用了模板方法模式的各个方面,类似于Herb Sutter所谓的“非虚拟接口习语”:

答案 2 :(得分:8)

我更喜欢使用后缀Core来命名我的虚拟或抽象方法,以表明该方法应包含执行某些操作的核心逻辑。

所有参数检查并引发我在方法中执行的可能事件,这些事件调用Core-Methods。

  abstract class Animal {
    public void Walk() {
      // TODO: do something before walking 
      // possible Argument checks and event raising

      // custom logic implemented by each subclass
      WalkCore();

      // TODO: do something after walking
    }

    protected abstract void WalkCore();
  }

  class Dog : Animal {
    protected override void WalkCore() {
      // TODO: walk with 4 legs
    }
  }

  class Bird : Animal {
    protected override void WalkCore() {
      // TODO: walk with 2 legs
    }
  }

我认为没有正式的命名准则,这取决于你。但它应该与您定义的所有类和虚拟/抽象方法保持一致。

如果您遵循模板方法并希望提供可扩展性点,则"Framework Design Guidelines"建议使用 Core 后缀。

答案 3 :(得分:3)

好问题。该模式是有效的,我使用它很多。我也同意WalkInternal不是一个理想的名字。

在这个例子中,我相信你没有正确地解决问题。

不要重命名“内部”方法,而是查看“外部”公共方法。它被称为Walk,但它有代码段(//do something before walking//do something after walking),它清楚地表明它不仅包含“行走”的逻辑。也许这种方法应该被称为ExerciseGoToTheShops - 或者您可以想到的任何描述您正在做的事情的创意名称。无论方法是什么,它绝对是步行+其他一些前/后步行动作的超集。

我最近开发的类似示例有一个名为Complete的公共方法和一个名为Save的虚拟方法,因此:

  • 每个班级都需要“完成”
  • 不同的实现会有自己的“保存”方法
  • '完成'还会执行一些验证,通知等

总之,抽象方法应该被称为Walk,而应该将您的公共方法重命名为更准确地描述“做某事/走路/做某事”过程的事情。


编辑:如果Walk类没有向WalkInternal类添加任何重要值或逻辑,那么我会质疑它是否是必需的。如果它确实添加了逻辑,则应重命名它以反映其新功能。

答案 4 :(得分:2)

我使用下划线大写情况的约定来进行抽象覆盖,所以Dog._Walk,虽然我偶尔会怀疑是否有更好的方法。

我比WalkInternal更喜欢DoWalk - 它更短,更舒适;传达了一种快速和前瞻性的想法。 “做”任何事情都会让我误以为止,就像“我的”对象那样。我喜欢我的下划线,其次是大写字母会议,但仍然是。

现实生活中的好问题

干杯,
Berryl

答案 5 :(得分:0)

对于提供模板方法主要行为的方法,我使用WalkOverride之类的名称。基类将它实现为protected abstract方法(派生类必需提供实现)或protected virtual空/非空方法(派生类可以可选提供/覆盖实现)。可以在Microsoft的各种XAML框架中找到示例,其中包含MeasureOverrideArrangeOverride等方法。 (WalkCore模式@Jehof提及用于命名模板方法本身。)

对于派生类可以为其自身目的而选择响应的“事件”(与定义模板方法的行为相反),我使用OnWalking和{{1}之类的名称}}。这些中的每一个通常在基类中实现为具有空方法体的OnWalked方法。

答案 6 :(得分:0)

此模式的名称为“ Template Method Pattern

在C#中,要被派生类覆盖的方法以“ On”开头。这种命名背后的逻辑是,派生类是对概念上内部事件的响应的自定义。这导致与C#的其他(现在已弃用的)使用“ On”引发事件产生了一些混淆,但这是C#特有的旧问题,并且不再存在。

class BaseClass
{
    protected virtual void OnInitialize() {};
    private PreInitialize() {}
    private PostInitialize() {}
    void Initialize()
    {
       PreInitialize();
       OnInitialize();
       PostInitialize();
    }
}

class DerivedClass : BaseClass
{
    protected override void OnInitialize() { /*do whatever*/ }
}

答案 7 :(得分:-2)

方法是采取行动的手段,按照规则进行操作,方法名称应该是动词或动词短语。它适用于方法,无论它们在何处声明。对我来说Dog.Walk看起来比Dog.WalkInternal.And更自然。是的命名方法更多的是指导而不是设计模式:)。如果你是.Net的人,那么我将推荐Brad Adam和Krzystof Cwalina的“Framework Design GuideLines”一书,它清楚地解决了这些问题。