我目前正在开发一个Java平台,我为它编写了自己的游戏引擎Bonsai.现在我问自己一个问题"我是否过度使用静力学?".
一方面它非常方便,因为我不必像地图或播放器那样在每个类中保持对游戏实例的引用.另一方面......我已经不得不剥离applet支持,因为那里的所有静态内容非常错误.
所以我的问题是,既然你可能比我更有经验的Java程序员,我应该摆脱所有静态吗?如果是的话,什么才能成为这样的有效方法:
public void draw(Graphics2D) {
if (this.game.time() > this.timer) {
this.game.image.draw(this.tiles[this.game.animation.get("tileAnim")], x, y, null)
}
}
Run Code Online (Sandbox Code Playgroud)
代替:
public void draw(Graphics2D) {
if (Game.time() > this.timer) {
Image.draw(this.tiles[Animation.get("tileAnim")], x, y, null)
}
}
Run Code Online (Sandbox Code Playgroud)
甚至在地图编辑器中更糟糕:
public void control() {
if(this.map.game.input.keyPressed(...)) {
this.map.game.sound.play(...);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
根据答案我决定有一个GameObject类,它为每个组件提供包装器方法.地图,播放器等然后从它的子类,这样我所有this.game调用都隐藏在场景后面,它仍然在前端看起来很好:
public class GameObject {
private Game game;
public GameObject(Game g) {
game = g;
}
public Game Game() {
return game;
}
public GameAnimation Animation() {
return game.animation;
}
public GameInput Font() {
return game.input;
}
// ...
public long Time() {
return game.time();
}
}
Run Code Online (Sandbox Code Playgroud)
现在代码看起来像这样:
public class Player() {
public Player(Game g, int xpos, int ypos) {
super(g);
// do other stuff
}
public void jump() {
// jump code
Sound().play("jump");
}
}
Run Code Online (Sandbox Code Playgroud)
或者这是更糟糕的Java?
EDIT2
好的我已经遇到了使用方法调用的问题,编译器给了我错误,因为它无法在原始的方法中找到我的子类游戏的方法,我想我会在这里使用普通字段.
EDIT3
好了我的 GameObject类现在看起来像这样,一切正常,我可以重新实现applet支持:)
public class GameObject {
protected Game game;
protected GameAnimation animation;
protected GameFont font;
protected GameInput input;
protected GameImage image;
protected GameSound sound;
public GameObject(Game g) {
game = g;
animation = game.animation;
font = game.font;
input = game.input;
image = game.image;
sound = game.sound;
}
}
Run Code Online (Sandbox Code Playgroud)
首先.
你不必去除所有的静态代码,因为这样可以使它在"纸上"更好.
你真的必须要了解实例代码(非静态)和类代码(静态)之间的区别
当方法/属性不需要类的实例工作时,使用静态代码(类方法/属性).一个很好的例子是图像绘制方法:Image.draw()
实例方法/属性对于保持给定对象的状态非常有用,该状态必须与其他对象中的数据分开.
例如,如果你Player在游戏中有课程并且你有两个实例player1,player2那么每个实例都有自己的分数:
public class Player {
private int score;
private String name;
etc.....
}
Player one = new Player("Player 1");
display( one.score );
Player two = new Player("Player 2");
display( two.score );
Run Code Online (Sandbox Code Playgroud)
而不是必须创建工件来保持每个玩家得分(比如将它们放在数组中,其中每个索引都是属性并使该数组静态等等)
其次
您可以object1.atr2.other.next.etc通过为对象分配适当的属性并以正确的方式执行封装来减少您提到的构造.
如果一个对象b需要访问另一个对象的第N个元素,a那么很可能所述属性属于该对象b而不是a或者该对象a应该提供一种方法来避免暴露它的内部.
它甚至使代码更容易阅读:
即.
public void draw(Graphics2D) {
if( this.game.needsDrawing() ) {
this.game.draw();
}
}
Run Code Online (Sandbox Code Playgroud)
代替:
public void draw(Graphics2D) {
if (this.game.time() > this.timer) {
this.game.image.draw(this.tiles[this.game.animation.get("tileAnim")], x, y, null)
}
}
Run Code Online (Sandbox Code Playgroud)
同样,它取决于具体情况,可能存在您不需要实例的情况(再次,如Image的draw()实用工具方法)
最后.
实例方法允许您使用多态,而类方法则不允许(至少在Java和其他静态类型语言中).
因此,如果您的代码是实例代码,您可能会受益于使用运行时委派和多态.例如,如果所有代码都是静态的,则不能使用它的状态模式,但您可以使用实例代码:
class Game {
GameState state = GameState.getInitialState( this );
void run() {
while( state.alive ) {
do X Y Z
state.updateState();
}
}
}
class GameState {
Game context;
static GameState getInitialState( Game g ) {
return new StartGameState(g);
}
void updateState();
}
class StartGameState {
void updateState() {
if( this.context.someCondition() ) {
this.context.state = new MidGameState();
}
}
}
class MidGameState {
void updateState() {
if( this.context.someOtherCondition() ) {
this.context.state = new EndGameState();
}
}
}
class EndGameState {
void updateState() {
Game over...
}
}
Run Code Online (Sandbox Code Playgroud)
再一次,只有在面向对象时才有意义,就像对象具有需要数据的属性一样?如果不是,保持该部分代码静态可能是好的.
所有这些概念(封装,多态,抽象,继承等)都是OO技术的本质,并且在OOA/D中有所体现,虽然它们看起来像语法糖(并且大部分时间都是这样),但是当你的经历会告诉你应该有类代码和什么时候作为实例代码.
| 归档时间: |
|
| 查看次数: |
2763 次 |
| 最近记录: |