2016-04-23 81 views
0

我有一個類,其存儲在繼承一個dictionary.I一個「項」類有幾個從彼此繼承的類物品,解析和存儲類

實施例:

Item <- Commodity <- Weapon

這些類只是容器,它們沒有特定的方法而只有構造函數,它們只保存信息。

在ItemManager類中我有一個方法獲取傳遞的字符串表示文本文件的名稱(沒有格式)。通過使用這種格式,我還知道通過給該方法分割線作爲數組來調用哪種方法來將該文件中的一行解析爲類實例。

我該如何使它在那些處理項目的方法中不需要編寫重複的字段分配?

實施例:

在從陣列我有tmpItem.id=int.parse(line[0])和在生成的武器我有tmpWeapon.id = int.parse(line[0])的方法生成的項目的方法。

我做錯了嗎?如何有效地將一行文本解析爲知道繼承關係的對象(考慮調用基礎構造函數的構造函數)。

+0

爲包含不同類型(如武器)的物品生成類。你可以使用結構,但結構已經過時了。 – jdweng

+0

我已經有了,那不是我需要:) –

+0

是的,你確實需要它。它是您聲明id屬性的基類的項目的基類,那麼您不必在繼承的類中再次聲明它。在繼承的類中,您可以使用項目類中的任何項目。 – 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; } 
} 

編輯 爲改變每班級行數而增加的解決方案

+0

我想到了這一點,但一個問題是,我將不得不知道調用基類後的索引。假設我有32行的東西,我只需要13行用於基類,然後剩餘的用於我的當前類。如果我改變了基類中的某些內容以需要16行,我將不得不更新硬編碼的13到16,並且存在忘記這樣做的風險:D –

+0

@Rareş:您可以傳遞額外的偏移量參數,或者傳遞只有其餘的字符串。儘管如此,我不會使用構造函數 - 單獨的解析方法也可以工作,而不需要將您的類綁定到任何特定的輸入格式:「ParseWeapon」會調用ParseCommodity,而ParseCommodity又會調用ParseItem,正在構建下一個方法的項目以及該方法所需的線條。 –

0

它很好,你意識到你正在複製解析代碼並想修復它。

如果所有類都繼承自Item類,那麼將公共屬性移入此類並從此處解析它。例如。

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

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

現在所有的繼承類將具有相同的解析方法,他們可以使用它,但這種方式可以刪除重複。

這是我想到的一個最簡單的例子。我想接下來你想有一個方法可以解析所有東西並設置這些屬性,但我不知道你的策略是什麼。但請記住,如果您想刪除重複,那麼最簡單的方法就是將該代碼移到基類中(雖然它總是不是最好的情況,但我認爲您此時不需要擔心)。

已更新:讀您的評論之後,我改變了代碼下面它可以幫助你的東西

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

只是想知道這裏,如果你不使用虛擬方法或未實現的方法 – Needham

+1

優點,這是一個抽象類是什麼點。我猜@Rares知道如果「Item」類將被實例化,或者這個方法會在子類中被覆蓋,但我會修改我的代碼以使其具有虛擬方法。 – adeel41

+0

私人CommodityC ProcessCommodity(字符串[]條目) { CommodityC tmpCommodity = new CommodityC(); int i = 0; tmpCommodity.id = int.Parse(entries [i ++]); tmpCommodity.name = entries [i ++]; tmpCommodity.minPrice = float.Parse(entries [i ++]); tmpCommodity.volume = float.Parse(entries [i ++]); tmpCommodity.mass = float.Parse(entries [i ++]); tmpCommodity.description = RemoveTabs(entries [i]); return tmpCommodity; } –