- PR -

protected フィールド は良くない?

1
投稿者投稿内容
がらす
ベテラン
会議室デビュー日: 2005/07/14
投稿数: 99
投稿日時: 2006-03-09 08:54
以下のように、親クラスで定義したフィールドの内容を子クラスで定義しています。今まで随分長い間この方法を使っていたのですが、FxCopで「protected フィールドは止めとけ」とワーニングが出てしまいます。
コード:

public class Base
{
protected string m_name;
public string Name { get{return m_name;} }
}

public class Derived : Base
{
public Derived() { m_name = "Class A"; }
}



なぜ良くないのか、色々考えて見たのですが分かりません。
C++を使っていた頃はしょっちゅう使っていたのですが、C#ではC++と事情が違うのでしょうか?それとも、C++でも良くないことをずっとやっていたのでしょうか?

個人的にはこれが一番シンプルで良い書き方だと思っていたのですが、他に良い方法があればご教示ください。どうぞよろしくお願いします。

[ メッセージ編集済み 編集者: がらす 編集日時 2006-03-09 09:19 ]
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-03-09 09:01
引用:

がらすさんの書き込み (2006-03-09 08:54) より:

protected readonly m_name;


protected static readonly ならばどうでしょうか?

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
がらす
ベテラン
会議室デビュー日: 2005/07/14
投稿数: 99
投稿日時: 2006-03-09 09:26
引用:

じゃんぬねっとさんの書き込み (2006-03-09 09:01) より:
protected static readonly ならばどうでしょうか?



どうもすみません、最初に書いたコードが間違ってましたので編集しました。

まず、readonly を使うと、自分のコンストラクタでしか値を設定できません。子クラスのコンストラクタでやろうとするとコンパイルエラーになります。それから、変数の型を書き忘れていました。すみません。

で、上記のコードではフィールドを private か internal にしろとFxCop(VS2005ではCodeAnalysis)が言います。staticをつけると non-public か const にすることも考えてみろよ、と言われます。protected は public の一部のようです。

と言うわけで、何が何故良くないのでしょうか。

[ メッセージ編集済み 編集者: がらす 編集日時 2006-03-09 09:33 ]
がらす
ベテラン
会議室デビュー日: 2005/07/14
投稿数: 99
投稿日時: 2006-03-09 09:32
試しに、言われたとおりにフィールドを private にしてみました。それでは Derived クラスで値を設定できないので、プロパティに setter も加えました。
コード:
    public class Base
    {
        public Base(){}
        private string m_name;
        public string Name { 
            get{return m_name;}
            set{ m_name = value; }
        }
    }

    public sealed class Derived : Base
    {
        public Derived() { Name = "Class A"; }
    }



これならば文句は言われなくなりましたが、逆にどこからでもm_nameを変えられるようになってしまっていて、最初のコードより危険になっている気がします。何故こちらの方が良いのでしょうか?
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2006-03-09 10:00
コード:
public class Base
{
    public Base(){}
    private string m_name;
    public string Name { 
        get{return m_name;}
    }
    
    protected void SetName( string name )
    {
    	m_name = value;
    }
}



やるとしたらこうでしょうか.
C#2.0ならば

コード:
public class Base
{
    public Base(){}
    private string m_name;
    public string Name { 
        get{return m_name;}
        protected set{ m_name = value; }
    }
}



元のコードが駄目かどうかは,議論の分かれるところでしょうが,派生クラスが基本クラスのフィールドを自由に触れるというのは,オブジェクト指向的にいかがなものか,ということでしょうね.
_________________
囚人のジレンマな日々
NAL-6295
ぬし
会議室デビュー日: 2003/01/26
投稿数: 966
お住まい・勤務地: 東京
投稿日時: 2006-03-09 10:03
NAL-6295です。

もし、サブクラスで一度設定されるだけでよい値ならベースクラスに

public abstract string Name{get;}

として、サブクラスではそれをオーバライドするというのはどうでしょう。

フィールドを持つ必要が無いので、フィールドが何処で変更されるかを気にする必要がありません。

[ メッセージ編集済み 編集者: NAL-6295 編集日時 2006-03-09 10:09 ]
スープカレー
会議室デビュー日: 2005/11/28
投稿数: 5
投稿日時: 2006-03-09 10:26
public class Base
{
private string m_name;
public string Name { get{return m_name;} }

protected Base(string name){
m_name = name;
}
}
public class Derived : Base
{
public Derived() : base("Class A"){
}
}

というのもありでしょうか。サンプルが単純なので目的に沿うものかどうかはよくわからないですが設計によってFactoryMethodを利用するなどいくつか方法があると思います。

>なぜ良くないのか、色々考えて見たのですが分かりません。
>C++を使っていた頃はしょっちゅう使っていたのですが、C#ではC++と事情が違うので
>しょうか?それとも、C++でも良くないことをずっとやっていたのでしょうか?

囚人さんのおっしゃるように言語というよりオブジェクト指向での設計上よくないのでしょう。サブクラスからは制約なしに値の代入を行えてしまう訳ですからnullや無効な値の代入のチェックが行えず危険性が増すということをFxCop的には言いたいのではないでしょうか。
1

スキルアップ/キャリアアップ(JOB@IT)