C# 給CardLib添加深度復(fù)制
使用ICloneable接口,復(fù)制Caixl、Cards和Deck對象,這在某些撲克牌游戲中是有用的,因為在這些游戲中不需要讓兩副撲克牌引用同—組Caid對象,但肯定會使一副撲克牌中的牌序與另一副牌的牌序相同。
在ChllCardLib中,對Can!類執(zhí)行復(fù)制操作是很簡單的,因為只需要進(jìn)行淺度復(fù)制(Card只包含值類型的數(shù)據(jù),其形式為字段)。我們只需要對類定義進(jìn)行如下修改:
public class Card : ICloneable
{
public object Clone() => MemberwiseClone();
ICloneable接口的這段實(shí)現(xiàn)代碼只是一個淺度復(fù)制,無法確定在Clone()方法中執(zhí)行了什么操作,但這己經(jīng)足以滿足我們的需要。
接著,需要對Cards集合類實(shí)現(xiàn)ICloneable接口。這個過程稍復(fù)雜些,因為涉及到復(fù)制源集合中的每個Gmi對象,所以需要進(jìn)行深度復(fù)制:
public class Cards : CollectionBase, ICloneable
{
public object Clone()
{
Cards newCards = new Cards();
foreach (Card sourceCard in List)
{
newCards.Add((Card)sourceCard.Clone());
}
return newCards;
}
最后,需要在Deck類上實(shí)現(xiàn)ICloneable接口。這里存在一個小問題:因為Chi ICardLib中的Deck類無法修改它包含的撲克牌,所以沒有洗牌。例如,無法修改有給定牌序的Deck實(shí)例。為解決這個問題,為Deck類定義一個新的私有構(gòu)造函數(shù),在實(shí)例化Deck對象時,可以給該函數(shù)傳遞一個特定的Cards集合。所以,在這個類中執(zhí)行復(fù)制的代碼如下所示:
public class Deck : ICloneable
{
public object Clone()
{
Deck newDeck = new Deck(cards.Clone() as Cards);
return newDeck;
}
private Deck(Cards newCards) => cards = newCards;
再次用一些簡單的客戶代碼進(jìn)行測試。與以前一樣,這些代碼應(yīng)放在客戶項目的MainO方法中,以便進(jìn)行測試:
Deck deckl = new Deck();
Deck deck2 = (Deck)deckl.Clone();
WriteLine($"The first card in the original deck is: {deckl.GetCard(0)}");
WriteLine($"The first card in the cloned deck is: {deck2.GetCard{0)}");
deckl.Shuffle();
WriteLine ("Original deck shuffled.");
WriteLine($"The first card in the original deck is: {deckl.GetCard(0)}");
WriteLine($"The first card in the cloned deck is: {deck2.GetCard(0)}");
ReadKey();
其輸出結(jié)果如圖所示。
點(diǎn)擊加載更多評論>>