2

そもそもこれは設計が悪いのかもしれませんが、私は抽象基底クラスを持っていて、それにはメソッドがありますvalidate

public abstract class abClass{
  string str1;
  string str2;

  public virtual bool validate(){...};
}

すべての派生クラスには検証が必要なプロパティがあることはわかっていますが、抽象メソッドごとstr1に検証をコピーして貼り付ける必要はありません。str2

将来の開発者 (私自身を含む) が、validate メソッドを含めて入力することを忘れないようにしたいと思います。私が見たところ、抽象メソッドに定義を与えたり、仮想メソッドを強制的にオーバーライドしたりする方法はありません。

これに関して私がこれまでに聞いたのは、「開発者がやりたいことを選択できるようにするべきだ」ということだけです。それは私にとって十分ではありません。間違いを犯さないようにするための抑制と均衡に反します。彼らが積極的に実装コードを持たないことを選択してもかまいませんが、忘れると、後で派生フィールドが検証されないときに頭痛の種になります。

この問題に対する提案はありますか?

4

3 に答える 3

6

Template メソッドパターンを使用できます。

public bool Validate()
{
    // Call base class validation
    if (!ValidateCore())
        return false;

    // Call specific validation code (overridden by derived classes)
    return ValidateOverride();
}

private bool ValidateCore()
{
    // Validate str1 and str2
    // ...
}

protected abstract bool ValidateOverride();

このように、派生クラスは (抽象であるため) オーバーライドする必要があり、基底クラスの非仮想メソッドによって呼び出されるため、ValidateOverrideを呼び出すことを忘れることはできません。ValidateCore

于 2014-07-01T20:45:43.827 に答える
5

この正確な問題については、Martin FowlerCallSuperの記事で説明しています。

彼は基本的に、クラスのサブクラスがオーバーライド時に基本クラスのメソッドを呼び出すことを要求するのは悪い習慣またはアンチパターンであると述べています。

Call Super は、オブジェクト指向フレームワークでときどき発生するマイナーな臭い (または必要に応じてアンチパターン) です。その症状は非常に簡単に見つけることができます。フレームワークにプラグインするために、スーパークラスから継承しています。ドキュメントには、「独自のことを行うには、プロセスメソッドをサブクラス化するだけです。ただし、スーパークラスへの呼び出しでメソッドを開始することを忘れないでください」のようなものがあります。

彼が提案した解決策は、基本クラスがそれ自体で必要なことを処理し、派生クラスには派生クラスの懸念のみを考慮させるというものです。

代わりに、API がハウスキーピング コールを記憶する必要があります。これを行う通常の方法は、次のようにハンドル メソッドをTemplate Methodにすることです。

//translation of java code to proper C#
public abstract class EventHandler ...
{
    public void Handle (BankingEvent e) 
    {  
        HouseKeeping(e); //this is required by the base class.
        DoHandle(e); //Here, control is delegated to the abstract method.
    }

    protected abstract void DoHandle(BankingEvent e);
}

public class TransferEventHandler: EventHandler
{
    protected override void DoHandle(BankingEvent e) 
    {
       initiateTransfer(e);
    }
}
于 2014-07-01T20:54:09.673 に答える
0

次のようなことができます。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            Base good = new Good();

            Base bad = new Bad();

            good.Validate();

            bad.Validate(); // This blows up

            Console.ReadLine();
        }
    }

    public class Base
    {
        public virtual void Validate()
        {
            throw new NotImplementedException();
        }
    }

    public class Good : Base
    {
        public override void Validate()
        {
            Console.WriteLine("Looks good to me.");
        }
    }

    public class Bad : Base
    {

    }
}

...とはいえ、私なら、Validate() メソッドを使用してインターフェイスを定義するだけです。

于 2014-07-01T20:49:57.910 に答える