亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

2個對象可以相互引用嗎?

2個對象可以相互引用嗎?

C#
肥皂起泡泡 2022-08-20 17:14:25
我正在用C#制作一個國際象棋游戲。我有2個類,Field和Piece:public class Field{    // the piece that is standing on this field    // null if no piece is standing on it    public Piece piece { get; set; }}public class Piece{    // the field this piece is standing on    public Field field { get; set; }}當一個棋子移動時,調用此方法(在類棋子中):public void Move(Field field){    this.field = field;    field.piece = this;}這似乎不是很好的編碼,因為每次我更改字段屬性時,我還必須更改該字段的 piece 屬性。不過,我確實需要這兩個屬性,因為在我的代碼的其他地方,我需要它們來執行檢查等(例如,這塊是什么字段,這個字段由哪一部分組成)。我的問題是:這完全沒問題,是代碼有難聞還是完全錯誤?解決這個問題的好解決方案是什么?有什么建議嗎?提前致謝!
查看完整描述

2 回答

?
墨色風雨

TA貢獻1853條經驗 獲得超6個贊

我在這里看到的問題是你有公共財產。這意味著其他人可以設置這些屬性,而無需更新相應的屬性。Piece.fieldField.piece


此外,當您將一個片段從一個字段移動到另一個字段時,您不會從上一個字段中刪除該片段,并且我們允許片段移動到占用的正方形,這將導致多個片段引用同一字段,但該字段將僅引用放置在那里的最后一個片段。


為了解決這些問題,我將屬性設置為只讀(使用私有 setter),強制客戶端調用相應的或方法來更改它們。然后,在此方法中,我們可以驗證要移動到的字段是否未被占用(如果是,我們只需拋出一個異常 - 客戶端必須在調用之前首先檢查這一點),并且我們從中清除。SetMoveMovePieceField


驗證工作可以在 或 類中完成,也可以同時在兩者中完成。我把它們都放在課堂上,以簡化事情。FieldPieceField


即使如此,這也存在問題。您可以直接調用(而不是 ),這將使該片段的值為 。所以這只是一個小小的改進,但不是理想的解決方案。請參閱下文以獲取更好的想法。Field.SetPiece(piece)Piece.MoveTo(field);nullField


public class Field

{

    public Piece Piece { get; private set; }

    public bool Occupied => Piece != null;


    public void ClearPiece()

    {

        // Remove this field from the piece

        if (Piece?.Field == this) Piece.MoveTo(null);


        // Remove the piece from this field

        Piece = null;

    }


    public void SetPiece(Piece piece)

    {

        if (piece != null)

        {

            if (Occupied)

            {

                throw new InvalidOperationException(

                    $"Field is already occupied by {Piece}.");

            }


            // Remove piece from the piece's previous field

            if (piece.Field?.Piece == piece)

            {

                piece.Field.ClearPiece();

            }

        }


        Piece = piece;

    }

}


public class Piece

{

    public Field Field { get; private set; }


    public void MoveTo(Field field)

    {

        field.SetPiece(this);

        Field = field;

    }

}

在對此進行了更多思考之后,我認為更好的解決方案是擁有一個處理所有驗證和移動的類,然后我們可以使和類“愚蠢”。GameManagerFieldPiece


這是有道理的,因為在 上設置 a 之前,還有很多驗證要做。是否可以將此部分移動到該位置(即,如果國王正在檢查并且這不會阻止它,那么就不允許這樣做)。根據棋子的移動規則(即不允許主教的水平位置),棋子的有效著陸點是否有效?是否有任何東西阻擋了到達目的地的路徑?目的地是否被屬于同一玩家的另一塊棋子占據?在移動一塊之前,需要評估很多事情。PieceFieldField


此外,這將允許我們在其他類型的游戲中重用 和 類,這些游戲可能具有不同的規則集,并且執行它們也不同。PieceFieldGameManager


查看完整回答
反對 回復 2022-08-20
?
繁華開滿天機

TA貢獻1816條經驗 獲得超4個贊

不!這與循環依賴的概念有關。雖然應用于模塊,但這很可能被視為此類模塊的前身。


更具體地說,這是相互遞歸對象的理想示例。從概念上講,如果替換(半偽代碼)


public class Field

{

    public Piece piece {

        public Field field {

            public Piece piece {

                ...

            }

        }

    }

}

這是因為對象是相互定義的。然后從理論上講,你可以做這樣的事情


this.field.piece.field.piece...


查看完整回答
反對 回復 2022-08-20
  • 2 回答
  • 0 關注
  • 147 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號