2016-04-23 13 views
0

私はdictionary.Iに「アイテム」クラスを継承する項目を格納するクラスを持っているが、解析および保存するクラス

例を互いから継承するクラスのカップルを持っています。

クラスは単なるコンテナであり、コンストラクタの特定のメソッドを持たず、情報のみを保持します。

ItemManagerクラスには、(フォーマットなしの)テキストファイルの名前を表す渡された文字列を取得するメソッドがあります。その形式を使用して、私はまた、配列に分割された行を渡すことで、そのファイルからクラスインスタンスに行を解析するために呼び出すメソッドを知っています。

どうすれば項目を処理するメソッドで重複フィールドの割り当てを記述する必要はありませんか?

例:私はtmpItem.id=int.parse(line[0])を有し、iはtmpWeapon.id = int.parse(line[0])を有する武器を生成する方法でアレイからアイテムを生成する方法で

これは間違っていますか?どのようにして、継承関係(基本コンストラクタを呼び出すコンストラクタを考えているか)を知っているオブジェクトを、効率的に解析します。

+0

武器のような異なるタイプを含むアイテムのクラスを生成します。あなたは構造を使うことができますが、構造は時代遅れです。 – jdweng

+0

私はすでにそれがあります、それは私が必要なものではありません:) –

+0

はい、それが必要です。これはidプロパティの基本クラスを宣言するitemの基本クラスで、継承されたクラスで再度宣言する必要はありません。継承されたクラスでは、アイテムクラスのいずれかのアイテムを使用できます。 – jdweng

答えて

0

が行にsplitedファイルの内容を取るコンストラクタを作成し、何かのお手伝いをし、ベースのコンストラクタを呼び出すことがあります。

public class Base 
{ 
    public const int LinesCount = 1; 
    public Item(string[] lines) 
    { 
     Id = int.Parse(lines[0]); 
    } 

    public int Id { get; } 
} 

public class Inherited : Base 
{ 
    public Inherited(string[] lines) : base(lines) 
    { 
     int index = base.LinesCount; 
     OtherProperty = int.Parse(lines[index++]); 
    } 

    public int OtherProperty { get; } 
} 

EDIT クラスごとの行数を変更するための追加されたソリューション

+0

私はこれを考えましたが、問題は基本クラスを呼び出した後にインデックスを知る必要があることです。私は32行で何かを持っているとしましょう、私は、私の現在のクラスの残りの部分は、基本クラスのための13行が必要になります。もし私が16行を必要とするベースクラスの何かを変更すると、ハードコードされた13を16に更新しなければならないでしょう。D –

+0

@Rareş:余分なオフセット引数を渡すか、残りの文字列のみ。でも、私はこのためにコンストラクタを使用することはありません - 別の解析メソッドを持つことは、特定の入力フォーマットにあなたのクラスを結ぶせずに、同じようにうまく機能: 'ParseWeapon'が順番に' ParseItem'を呼ぶことになる、 'ParseCommodity'を呼ぶだろう - それぞれのパスをメソッドが必要とする行だけでなく、次のメソッドへの構築中の項目。 –

0

あなたが解析コードを複製していて、それを修正したいことがわかってよかったです。

すべてのクラスがItemクラスから継承される場合は、共通プロパティをこのクラスに移動してここから解析します。例えば。

public abstract class Item 
{ 
    public int id { get; set; } 

    public virtual void ParseId(string line) 
    { 
    id = int.Parse(line); 
    } 
} 

今、すべての継承されたクラスが同じ解析方法を持っていますし、彼らはそれを使用することができますが、この方法で、あなたは重複を削除することができます。

これは私が思いつく最も簡単な例です。次は、すべてを解析してそれらのプロパティを設定できる1つのメソッドが必要ですが、私はあなたの戦略が何であるか分かりません。しかし、重複を取り除きたい場合は、そのコードをベースクラスに移動するのが最も簡単です(ただし、常に最良のケースではありませんが、現時点では心配する必要はありません)。

:あなたのコメントを読んだ後、私は以下にコードを変更したことが

public abstract class Item 
{ 
    public int id { get; set; } 
    public string name { get; set; } 
    public float volume { get; set; } 
    public float minPrice { get; set; } 
    public float mass { get; set; } 
    public string description { get; set; } 

    public virtual void Parse(string[] entries) 
    { 
     int i = 0; 
     id = int.Parse(entries[ i++ ]); 
     name = entries[ i++ ]; 
     minPrice = float.Parse(entries[ i++ ]); 
     volume = float.Parse(entries[ i++ ]); 
     mass = float.Parse(entries[ i++ ]); 
     description = RemoveTabs(entries[ i ]); 
    } 

    public string RemoveTabs(string line) { throw new NotImplementedException(); } 
} 

public class Commodity : Item 
{ 
} 

public class Weapon : Commodity 
{ 
} 

public class CommodityC : Item 
{ 
} 


public class ItemManager 
{ 

    private Item ProcessCommodity(string[] entries) 
    { 
     var commodity = new Commodity(); 
     var weapon = new Weapon(); 

     commodity.Parse(entries); 
     //weapon.Parse(entries); 
     return commodity; 
    } 
} 
+1

はちょうどこの点は、抽象クラスであることをいただきました、ここで疑問に思います。私は@Raresが "Item"クラスがインスタンス化されるか、このメソッドがサブクラスでオーバーライドされるかどうかを知っていると思いますが、バーチャルメソッドを持つようにコードを変更します。 – Needham

+1

優れたポイントを使用してアレント場合 – adeel41

+0

プライベートCommodityC ProcessCommodity(文字列[]エントリ) {CommodityC tmpCommodity =新しいCommodityC()。 int i = 0; tmpCommodity.id = int.Parse(エントリ[I ++])。 tmpCommodity.name =エントリー[i ++]; tmpCommodity.minPrice = float.Parse(エントリ[i ++]); tmpCommodity.volume = float.Parse(エントリ[i ++]); tmpCommodity.mass = float.Parse(エントリ[i ++]); tmpCommodity.description = RemoveTabs(entries [i]); return tmpCommodity; } –

関連する問題