6

私はC#に少し慣れていませんが、プログラミングのバックグラウンドはかなり豊富です。

私がやろうとしていること:ゲームにさまざまなMapTilesを定義します。基本のMapTileクラスを次のように定義しました。

public class MapTile
{
    public Texture2D texture;
    public Rectangle mapRectangle;

    public MapTile(Rectangle rectangle)
    {
        this.mapRectangle = rectangle;
    }
}

次に、次のようにサブクラスGrassTileを定義します。

class GrassTile : MapTile
{
    new Texture2D texture = Main.GrassTileTexture;
    new public Rectangle mapRectangle;

    public GrassTile(Rectangle rectangle) : base(rectangle)
    {
        this.mapRectangle = rectangle;
    }
}

私のメインクラスでは、次のような新しいマプタイルを作成しています。

Maptile testTile;
testTile = new GrassTile(new Rectangle(0, 0, 50, 50);

ただし、このtestTileをレンダリングしようとすると、テクスチャがnullになってしまいます。MapTile内でテクスチャを定義すると、コードは正常に機能するため、以前の実装とは何の関係もありません。

では、GrassTileでMapTileのメンバー変数テクスチャを変更できるようにするにはどうすればよいですか?または、メインクラスにMapTileの代わりにGrassTileのテクスチャを認識させます。インターフェイスもいじりましたが、インターフェイスメンバー変数を宣言できません。私がまだ取得していないC#継承に何か他のものはありますか?

前もって感謝します

4

5 に答える 5

8

子クラスは親クラスのメンバーを継承します。それらを指定する必要はありません。また、パブリック フィールドではなくプロパティを使用することをお勧めします。

public class MapTile
{
    public Texture2D Texture { get; set; }
    public Rectangle MapRectangle { get; set; }

    public MapTile(Rectangle rectangle)
    {
        MapRectangle = rectangle;
    }
}

public class GrassTile : MapTile
{    
    public GrassTile(Rectangle rectangle) : base(rectangle)
    {
        Texture = Main.GrassTileTexture;
    }
}
于 2013-01-16T22:43:12.213 に答える
2

構文が少し混乱しています。「new」キーワードは、メインで行うように何かをインスタンス化するための演算子として、または継承されたメンバーを非表示にするためのメンバーへの修飾子として使用できます。これは、GrassTileで行っていることです。あなたは本質的にそこであなたのメンバーを再定義しています。正しいバージョンは次のとおりです。

   class GrassTile : MapTile
    {
        public GrassTile(Rectangle rectangle) : base(rectangle)
        {
            texture = Main.GrassTileTexture;
        }
    }

とにかく、長方形がベースコンストラクターに設定されます。

于 2013-01-16T22:47:31.163 に答える
0

継承により、継承されたフィールドが派生クラスで永続化されます。

public sealed class GrassTile : MapTile
{
    public GrassTile(Rectangle rectangle) : base(rectangle)
    {
        texture = Main.GrassTileTexture;
    }
}
于 2013-01-16T22:52:09.480 に答える
0

newここで、キーワードの使用方法を明確にするのが最善だと思います。new2通りの使い方ができます。演算子および修飾子として。

new"オペレーター"

new 演算子は、オブジェクトを作成し、コンストラクターを呼び出すために使用されます。次に例を示します。

Class1 MyClass  = new Class1();

newモディファイア

基本クラスから継承されたメンバーを明示的に非表示にするには、new 修飾子を使用します。継承されたメンバーを非表示にするには、同じ名前を使用して派生クラスで宣言し、new 修飾子で変更します。

次のクラスを検討してください。

public class MyBaseC 
{
   public int x;
   public void Invoke() {}
}

派生クラスで Invoke という名前のメンバーを宣言すると、基本クラスのメソッド Invoke が非表示になります。つまり、次のようになります。

public class MyDerivedC : MyBaseC
{
   new public void Invoke() {}
}

ただし、フィールド x は同様の名前で隠されているわけではないため、影響を受けません。

継承による名前の隠蔽は、次のいずれかの形式を取ります。

  • クラスまたは構造体に導入された定数、フィールド、プロパティ、または型は、同じ名前を持つすべての基本クラス メンバーを非表示にします。

  • クラスまたは構造体に導入されたメソッドは、同じ名前のプロパティ、フィールド、および型を基本クラスに隠します。また、同じシグネチャを持つすべての基底クラス メソッドを非表示にします。

  • クラスまたは構造体に導入されたインデクサーは、同じシグネチャを持つすべての基本クラスのインデクサーを非表示にします。

名前を隠して型を宣言しているMaptileが、子GrassTile型に初期化していて、親MapTileTextureがメンバーを初期化していないことが、null.

于 2013-01-16T22:58:32.350 に答える
0

コードで改善すべき点がいくつかあります。

まず、プロパティTextureは基本クラス MapTile で既に定義されているため、クラスで再定義する必要はありませんGrassTile。派生クラス (GrassTile) は、基本クラス (MapTile) からこのメンバーを継承します。

次に、基本クラス 'MapTile' をabstractに変更することを検討してください。それ自体には直接的な動作はないと思われるためです (テクスチャは具体的な派生クラスの実装によって提供される必要があります)。

次に、このようにクラス階層の外で実際にアクセスするべきではないため、textureto be protectedの宣言を変更できます。または、getおよびsetアクセサーを使用してプロパティに変換します。

最後に、new修飾子の使用は正しくありません。この修飾子は、(このコンテキストでは) いくつかの動作の基本実装を (基本動作を継承するのではなく) 新しい動作でオーバーライドできるようにすることのみを目的としています。この場合、GrassTile で「新しい」テクスチャを宣言しています。これは (不要ですが) 基本インスタンスをオーバーライドしますが、GrassTile クラスを介して参照される場合のみです。

{
    MapTile m1 = new GrassTile(...);
    //m1.texture == null;
    GrassTile m2 = new GrassTile(...);
    //m2.texture = Main.GrassTileTexture
}
于 2013-01-16T23:06:57.847 に答える