8

私はこのようなロールプレイングゲームのクラス構造を持っています...

public abstract class Item
{
   public abstract string Name { get; set; }
}

public abstract class Armor : Item
{
   public override string Name { get; set; }
}

public class Helmet : Armor
{
   public override string Name { get; set; }
}

基本的に、すべての派生型に「名前」プロパティを含めるように強制しようとしています。これが最善の方法ですか?Item.Name から "abstract" を削除してから、アーマーとヘルメットの上書きされた "Name" プロパティを削除できることを知っています。これを行うと、コードは少しきれいに見えますが、これらの派生クラスで base.Name を設定するのを忘れる可能性があります。

誰かがこれを行うための最良の方法を教えてくれますか?

編集:申し訳ありませんが、私の質問をもう少し明確にさせてください。2点確認したい。1) Name プロパティがすべての派生クラスに存在する 2) Name プロパティが null または空ではない

私は基本的に、Item から派生した (抽象ではない) クラスに Name の値を持たせたいと考えています。

4

7 に答える 7

9

プロパティの初期化について心配しているようですね。

しかし、これらの派生クラスで base.Name を設定するのを忘れるかもしれません。

Name プロパティを強制的に設定する 1 つの方法は、次のように基本クラス コンストラクターにこのセッターを含めることです。

public class MyBaseClass
{
    private string _name;

    public MyBaseClass(string name)
    {
        _name = name;
    }
}

MyBaseClass から派生するものはすべて、そのコンストラクターを満たす必要があります。

public class MyDerivedClass
{
    public MyDerivedClass(string name) : base(name)
    {

    }
}

次に、プロパティを次のいずれかにすることもできます。

  • 独自の実装を持つ各派生クラスに存在することを保証する抽象
  • virtual を使用して基本実装を提供し、すべてをオーバーライドします。

上記が適切な設計であるかどうかについてはあえて触れませんが、インスタンス化されたときにすべての派生クラスが有効な名前プロパティを持つようにすることはできます。

他の回答が示唆するように、別のアプローチは、基本実装で例外をスローする仮想プロパティを実装することです。

于 2010-01-28T21:38:05.383 に答える
4

基本クラスで定義するだけNameでよく、abstract として指定する必要はありません。すべての派生クラスのプロパティとして引き続き使用できます。

public abstract class Item
{
   public string Name { get; set; }
}

public abstract class Armor : Item
{ }

public class Helmet : Armor
{ }
于 2010-01-28T21:22:26.013 に答える
2

すべての派生オブジェクトでプロパティ「Name」を使用したいだけであれば、継承されているため、abstract とマークする必要はまったくないという Mike の意見は正しいです。

アイテムが作成されるときに名前が確実に設定されるという事実を強制したい場合は、ゼロパラメーターのコンストラクターを非表示にして、名前を受け入れるコンストラクターを公開することで強制できます。

このコードを見てください:

public class Item
{
   public string Name { get; set; }

   public Item(string name)
   {
       this.Name = name;
   }

   protected Item() {}
}

public class Armor : Item
{   
   public Armor(string name) : base(name) {}
   protected Armor() {}
}

public class Helmet : Armor
{   
   public Helmet(string name) : base(name) {}
   protected Helmet() {}
}

上記の定義は、次のことを意味します。

Helmet myHelmet = new Helmet(); //will not build
Helmet myHelmet = new Helmet("Some Fancy Helmet Name"); //will build

Armor myArmor  = new Armor (); //will not build
Armor myArmor  = new Armor ("Some Fancy Armor Name"); //will build

Item myItem = new Item (); //will not build
Item myItem = new Item("Some Fancy Item Name"); //will build

これにより、クラスのインスタンスは作成時に名前を定義する必要があります。とにかく1つの可能な解決策...

于 2010-01-28T21:27:24.437 に答える
2

これを行うと、コードは少しきれいに見えますが、これらの派生クラスで base.Name を設定するのを忘れる可能性があります。

そうすると、オブジェクトの名前がばかげたものになってしまいます。

さらに良いことに、nameとして開始しましたnull。名前を初期化するのを忘れたが、誰かがそれを使用しようとすると、例外が発生し、修正する必要があることがわかります。

于 2010-01-28T21:25:19.967 に答える
0

それはあなたが何をしたいかによって異なります...

クラスを抽象化すると、すべてのサブクラスがクラス (およびその抽象関数など) を実装するようになりますが、関数をオーバーライドできる基本機能を関数に持たせたい場合は、クラスを作成しないことをお勧めします。抽象化し、代わりに特定の関数を仮想化します。したがって、仮想関数が上書きされていない場合、基本関数が呼び出されます。

同じ名前の「新しい」プロパティを作成するオプションは常にありますが、それは良い習慣ではないと思います。

それが役立つことを願っています。

于 2010-01-28T21:40:07.007 に答える
0

抽象クラス内でプロパティを仮想化できると思うので、問題は解決するはずです。

値を基本抽象クラスで特定のものに設定できます。ここに例を示します。

public abstract class Item
{
   public virtual string Name 
   { 
         get {return m_strName;} 
         set {m_strName = value;}
   }

public abstract class Armor : Item
{
   public override string Name { get; set; } // if you want to override it 
}

public class Helmet : Armor
{
   public override string Name { get; set; } // if you want to override it
}
于 2010-01-28T23:00:19.023 に答える
0

Name を仮想 ie にします。public virtual Name {get; set; }アクセサは Item クラスで使用できますか? Helment と Armor は Item クラスから派生しているためです。それらをオーバーライドする必要があることを強制します...

これがお役に立てば幸いです。よろしくお願いします、トム。

于 2010-01-28T21:26:09.357 に答える