14

今日コードレビューをしていて、ある開発者によって書かれた古いコードに出くわしました。それはこのようなものになります

public abstract class BaseControl
{
    internal abstract void DoSomething();
}

同じアセンブリ内に派生クラスがある場合、それは機能します

public class DerivedControl : BaseControl
{
    internal override void DoSomething()
    {
    }
}

ただし、別のアセンブリで基本クラスを派生させると、コンパイル時にエラーが発生します

DerivedControl does not implement inherited abstract member 'BaseControl.DoSomething()

それは私に考えさせました。メソッドを内部抽象として宣言するのはなぜですか?

4

4 に答える 4

12

元のプログラマは、派生コントロールをクライアント コードで使用できるようにしたいと考えていました。ただし、クライアントが仮想メソッドを継承して混乱させないようにしてください。これは悪い考えではありません。通常、メソッドをオーバーライドして、基本クラスのメソッドを呼び出すのを忘れるなどして、基本クラスを壊すのは簡単です。

于 2010-02-20T21:21:25.920 に答える
6

明らかなケースの 1 つは、メソッドが内部型を受け取ったり返したりする場合です。たとえば、WPF Transform クラスのコア メソッドは、WPF がパブリック API の一部として公開していない内部相互運用型を処理します。署名には内部型が含まれているため、メソッドを public または protected にすることはできません。それでも明らかに、さまざまな Transform クラスがポリモーフィックに機能することが適切です (必要です!)。したがって、Transform/GeneralTransform の基本メソッドは内部でなければなりません。

別の、しかし関連する理由は、外部派生を防ぐことです。結局のところ、WPF アーキテクトは、ユーザーが独自の Transform クラスを作成できるように、保護された抽象メソッドで内部相互運用型の "安全な" バージョンを公開できたはずです。非アフィン変換の作成など、人々がその機能を使用する方法に対処する必要がなかったので、そうしませんでした。外部派生を許可すると、WPF の他のクラスの仕事が非常に複雑になるため、アーキテクトは抽象メソッドを内部にすることで、「承認された」派生クラスのみを許可することにしました。

于 2010-02-20T20:36:34.770 に答える
1

私の最初の反応は、正当な理由はないというものでした。外部継承を防止したい場合は、クラスを内部としてマークする必要があります。しかし、それはクラスが他のアセンブリに対して完全に隠されていることを意味します。

このメソッドは、可視性を維持しながら外部継承を防ぐと思います。

于 2010-02-20T20:35:32.120 に答える
0

メソッドを内部抽象として定義することにより、同じアセンブリ内のクラスのみがメソッドの実装を持つことができるようにする必要があります。

そのDLLを配布すると、クライアントが実装を継承して台無しにすることを回避できます。

于 2010-02-22T12:24:30.450 に答える