我正在编写一个小游戏,我有两个类:Board
和Piece
。 Board
已(到目前为止)有一个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习惯用法?提前感谢您向我澄清这一点。
答案 0 :(得分:8)
这不是一个糟糕的方法。将this
传递给各种方法在编程中并不罕见。它只取决于你的设计,就我而言,Piece
类中没有任何内容。
Board
类中的一件事可能会令人困惑 - movePieceDown
方法。您有不可用的参数Board board
。如果您打算使用this
作为参数,请删除该属性,因为董事会不应该接收其他董事会作为潜在参数,事实上,不应该知道其他董事会可以存在。
最后,您可以确保Piece
将Board
的接口视为方法参数,并确保该合约永远不会更改。例如,它可以有这些方法:
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。