将对象本身(this)传递给字段的方法是一种糟糕的方法吗?

时间:2013-06-26 11:57:08

标签: java oop

我正在编写一个小游戏,我有两个类:BoardPieceBoard已(到目前为止)有一个Piece,可以Board的边框移动。

public class Board {
  private Piece piece_;
  private int width, height;
  ...

  movePieceDown() {
    piece_.moveTo(this, 1, 2);
  }
}

public class Piece {
  public boolean moveTo(Board board, int x, int y) {
    // move piece to new location (x,y)
    // return true if successful
  }
}

如果我在piece_.moveTo(this, 1, 2);传递给董事会的参考文件,那么如果董事会中没有障碍,那么Piece可以移动到新的位置,这是不好的方法吗?在没有通过参考董事会的情况下,Piece不知道新位置是否存在障碍或是否超出董事会边界。

在我看来,每个对象都应该只关心自己:片段应该移动到新的位置,如果合法移动,董事会应该担心,但是我发布的这个示例代码更有意义并简化了事情。 / p>

TL; DR:我是否通过将对象本身传递给字段的方法来破坏一些OOP准则,还是一些正常的OOP习惯用法?提前感谢您向我澄清这一点。

7 个答案:

答案 0 :(得分:8)

这不是一个糟糕的方法。将this传递给各种方法在编程中并不罕见。它只取决于你的设计,就我而言,Piece类中没有任何内容。

Board类中的一件事可能会令人困惑 - movePieceDown方法。您有不可用的参数Board board。如果您打算使用this作为参数,请删除该属性,因为董事会不应该接收其他董事会作为潜在参数,事实上,不应该知道其他董事会可以存在。

最后,您可以确保PieceBoard的接口视为方法参数,并确保该合约永远不会更改。例如,它可以有这些方法:

public interface IBoard { 
    public boolean isFieldFree(int x, int y)
    public Piece getPiece(int x, int y) 
}

无论您以后如何更改董事会的实施,这都应该始终有效,因此您在更改Piece时无需重新编写Board代码。通过这种方式,您可以强制执行Piece无法更改电路板状态的规则(在界面中,不要公开任何改变电路板状态的方法)。

答案 1 :(得分:3)

首先,为什么你的作品变量以下划线结尾?这很奇怪:p

至于你的问题。我会处理所有相关的事情,比如在班级内移动。如果你想知道你在板上的什么位置,我会在你的棋子类中有两个整数变量,叫做x和y。

这件作品不必知道它是否会与棋盘上的其他棋子相撞,因为这是你的棋盘类在移动棋子时应该处理的东西。

因此,例如,如果你将你的棋子移动到x = 1和y = 2,你应该让你的棋盘检查位置1,2上是否有一个棋子并做出相应的反应。

将“this”传递给另一个类的方法没有任何问题,但从松散耦合的面向对象编程的角度来看,它不是最优设计。

我的2美分:)

答案 2 :(得分:2)

我认为这是一个很好的策略,特别是当你需要将一堆局部变量传递给一个方法时。而不是传递所有这些本地人,只需传递对象的实例来整理你的方法签名。

请务必练习良好的封装,以便接收此参数的方法不会修改字段或调用旨在限制访问的方法。

答案 3 :(得分:2)

通常,传递this并不罕见,但这取决于具体情况。在这种情况下,它是上帝取决于实施细节。 Board有几个可以四处移动的管道,所以位置是一块的属性。但是,将一件从一个位置移动到另一个位置可能是该板的功能。例如,如果新位置已被占用,会发生什么?那件作品会移动其他部件吗?这适合您的设计吗?

根据你的签名,我希望moveTo功能接受一块板,这表明一块板可以从一块板移动到另一块板。在阅读代码时,这可能具有误导性,除非确实应该如此。

答案 4 :(得分:1)

我不确定你是否会通过这样做来制动任何面向对象的编程规则,但它看起来很奇怪,因为你在Board上调用一个方法然后这个方法唯一做的就是在Piece上调用一个方法,将自己作为参数传递。

面向对象编程很多关于将事物视为现实世界中的对象。按照这种方法,我会把它看作是板子上的那块,例如它的位置是由板子决定的,而不是它自己。从这种方法来看,移动这件作品是在板上完成的,而不是作品本身。

因此,即使将this作为参数传递并不正确,我宁愿定义方法:

public class Board
{
    private Piece p;
    // ...

    public boolean movePieceDown()
    {
        // Move the piece to a new location using it's setters
    }
}

除此之外,由于Board对象知道它的属性,因此生成的代码将更具可读性,因为您不必调用那么多的getter和setter(以检查边界)例如)。

答案 5 :(得分:1)

回答标题中的具体问题(而不是关于OO设计的一般意见):不,这不是不好的做法,而是相当普遍。

但是,请注意,不建议在构造函数中将this传递给外部世界,因为它可能会导致并发场景中出现令人讨厌的错误,其中接收方可能会看到源处于不一致状态。 / p>

答案 6 :(得分:0)

这是通过普通的方法调用隐式传递的。阅读我在论坛上找到的answer

您也可以阅读JVM specification