- - PR -
継承元のパブリックメソッドを外部に隠ぺいしたい
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2007-06-20 17:50
new がそれです。 GDNJ でも過去に同様の質問があったような気がしますが、Shadows だけでは解決できません。継承クラス側に Private メンバとして Shadows (new) したとしても、基底クラスの同メンバが上書きされるわけではないので、基底クラスの Public なメンバには外部からアクセスできます。 エディタに表示しないだけならば、System.ComponentModel.EditorBrowsable 属性なのでしょうけど、結局のところ使用不可になるわけではないですね。 _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||||||
|
投稿日時: 2007-06-20 18:03
アップキャストしなければ呼び出せないようになら。
Interface IA Sub AA() End Interface Public Class A Implements IA Private Sub AA() Implements IA.AA Debug.WriteLine("A-AA") End Sub End Class Public Class B Inherits A End Class Dim b As New B b.AA() 'ビルドできない CType(b, IA).AA() 'AのAAが呼ばれる Dim a As New A a.AA() 'こっちもビルドできない CType(a, IA).AA() 'AのAAが呼ばれる [ メッセージ編集済み 編集者: 未記入 編集日時 2007-06-20 18:05 ] | ||||||||||||
|
投稿日時: 2007-06-20 18:25
申し訳ございません。表現の仕方が悪かったです。
「コンパイルエラーとしたい==インテリセンスに出さないようにする」 と自分では判断していました。 EditorBrowsableAttribute属性でインテリセンスに表示しないこともできるのですね。 勉強になります。 ただし、派生クラスのインスタンスからのみ非表示にするということはできますでしょうか(都合が良すぎますでしょうか)。 実際には、コンパイルエラーとしたいのですが、 一郎さんの例をお借りすると、 コード: -------------------------------------------------------------------------------- class Base { public virtual void F() { Console.WriteLine("Base.F"); } public virtual void G() { Console.WriteLine("Base.G"); } } class Derived : Base { public override void F() { Console.WriteLine("Derived.F"); } } (コードの中) Derived d = new Derived(); Base b = d; b.F(); //出力 Derived.F b.G(); //出力 Base.G d.F(); //出力 Derived.F d.G(); //出力 Base.G(●希望としてはコンパイルエラーとしたい) -------------------------------------------------------------------------------- ●印の箇所でコンパイルエラーにするような技(?)があればと思ったのですが。 このようなことがはたして可能なのかの見分けができればと思いまして。 いま思いついたのですが class Derived : Base { public override void F() { Console.WriteLine("Derived.F"); } public override void G() { #error コンパイルエラー! } } というようにすればよいのですかね。 | ||||||||||||
|
投稿日時: 2007-06-20 18:33
すいません
#errorディレクティブの使い方間違えてました。 | ||||||||||||
|
投稿日時: 2007-06-20 18:39
ObsoleteAttribute使ったらできました。
Public Class A Public Sub AA() Debug.WriteLine("A-AA") End Sub End Class Public Class B Inherits A <Obsolete("使用不可", True)> _ Public Shadows Sub AA() Debug.WriteLine("B-AA") End Sub End Class Dim b As New B b.AA() 'ビルドできない Dim a As New A a.AA() | ||||||||||||
|
投稿日時: 2007-06-20 18:41
# 先に書かれちゃったけど、投稿しちゃえ。
継承クラス型からの呼び出しのみを防げれば良いのであれば、System.Obsolete 属性を使って使用禁止になるようにコンパイラに呼びかけてみるなんて方法がありますね。
たとえば、
これはコンパイル エラーとして防ぐことができます。
このように基底クラス型からの呼び出しについては防ぐことはできません。ご注意ください。 _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||||||
|
投稿日時: 2007-06-20 18:43
無理。 委譲(オブジェクトコンポジション)じゃダメなの?
ってな感じ。 [追記] # 話が進んでいるのにも気づかず、とんちんかんな回答しちゃったよ。 # さっくり、無視しちゃってください。 [ メッセージ編集済み 編集者: かずくん 編集日時 2007-06-20 18:49 ] | ||||||||||||
|
投稿日時: 2007-06-20 18:49
リファクタリングというのをご存知でしょうか。
リファクタリングのきっかけとする不吉な匂いの中に「相続拒否」というのがあります。 つまり親クラスの機能などを引き継ぎたくないということです。 例えば、Carクラスにクラッチを操作する機能がpublicで定義されていたとします。 オートマチックトランスミッションの車(ATCar)クラスをCarクラスを継承して作った場合に、クラッチを操作する機能が外部に公開されているのは問題です。 そこで、ATCarクラスではクラッチ操作の機能を隠したいと思うわけですが、この場合まずクラス構成自体に疑問を持たなければいけません。 クラスの継承というのは、子クラスが親クラスそのものであるときに使用します。 よくある間違いは「親クラスの機能を使いたいから継承」というパターンです。 上の例で、Carクラスにクラッチ操作の機能がpublicで定義されているということが間違っていないとすると、車というのは外部からクラッチ操作ができるものということになります。 すると、ATの車は車ではありませんので、ATCarがCarを継承するのは間違いです。 クラッチ操作の機能が公開されていないものでも車でありうるなら、Carクラスにクラッチ操作の機能が定義されている事自体が間違いですのでそれを改めなければいけません。 クラッチ操作の機能が付いているのは車の中でもMTの車ということですので、Carから継承したATCarとMTCarというクラスを作り、それぞれのクラスにはそれぞれのクラスの機能を定義することになります。 そもそも、クラス(B)はクラス(A)の機能を使っているというだけなら、継承はせずにクラス(B)がクラス(A)に処理をお願いするような形になります。委譲って言いますけど。 [ メッセージ編集済み 編集者: 一郎 編集日時 2007-06-20 18:54 ] |