Can I make an Object immutable when passed as a parameter,
so that the called method can't change it but the callee can?
So I have somthing like this:
Class Car {
Wheel wheel_1;
Axis axis = new Axis(wheel_1);
}
Class Wheel {
int size;
setSize(int size) {}
int getSize() {}
}
Now I construct a car with a wheel. Then from class car I want to construct an axis.
For that I pass wheel_1 to the constructor of Axis.
Now my question: Can I asure somehow that the constructor of Axis doesnt change the size of wheel_1 but class car can change it.
Yes. Typically this is done by utilising a copy-constructor for the Wheel class.
For example:
wheel_1 = new Wheel(wheel);
Bear in mind, the Wheel class will need to be written in a way that supports this. That is, it should either offer a copy-constructor.
Note: this hasn't made the object immutable. It has merely produced a copy that can't be edited by anything outside your class.
If you return the Wheel instance from any of your other methods, be sure to defensively copy it on the way out too:
Wheel getWheel() {
return new Wheel(wheel_1);
}
Finally, it's worth mentioning that it's always a good idea to create immutable classes whenever you can. So perhaps you can avoid this issue by actually making Wheel immutable?
Make the Wheel class immutable. Then let the Car object create a new Wheel object when it needs a new size.
public final class Wheel {
private final int size;
public Wheel(int size) {
this.size = size;
}
public int getSize() {
return size;
}
}
Now you can pass the wheel object to the Axis without any problems.
public class Car {
private Wheel wheel;
private Axis axis;
public Car(int initialWheelSize) {
wheel = new Wheel(initialWheelSize);
axis = new Axis(wheel);
}
}
Pass the Axis constructor a copy of wheel_1.
class Car {
Wheel wheel_1;
Axis axis = new Axis(new Wheel(wheel_1));
}
Also, Wheel will need a constructor which takes another Wheel object and copies its properties.
Why don't you send the parameter as its superclass which doesn't have setSize() method
Class Car {
Superwheel wheel_1;
Axis axis = new Axis(wheel_1);
}
class Superwheel
{
int size;
int getSize() {}
}
Class Wheel extends Superwheel{
int size;
setSize(int size) {}
int getSize() {}
}
I would have Wheel implement an interface that has only accessor methods, i.e: -
Example
interface WheelInterface
{
int getSize();
}
class Wheel implements WheelInterface
{
// methods
}
class Axis
{
public Axis(WheelInterface wheel)
{
// Only getSize will be available
}
}
Now, simply pass WheelInterface instead of Wheel and only the accessor methods will be available to the constructor of your Axis class
Benefits
The benefits of doing this is that there is no copying required; you are simply providing a contract to the Axis class and that contract states that it can only get the size, not change it.
By passing the same object reference by value, you aren't having to call any copy constructor and don't have to worry about deep and shallow copying semantics. I would not want to use Clone on my wheel, I think that feels a little dirty for reasons mentioned in comments of other answers.
In an object-oriented pattern, using an interface to abstract away what you don't need is also a sign of good design. If your wheel has snow tyres on, your Axis class probably doesn't even need to care!
Drawbacks
As others have mentioned, it is possible to cast the interface back to a concrete type (as others have mentioned, assuming you know what you're casting to); this is called downcasting and I don't recommend it; if this were done in a similar scenario, it probably wouldn't get past a code review.
Yes, you can. If you make Car and Wheel in the same package and declare Wheel setter fields to be protected. So, Axis if declared in another package can't access setters of Wheel, thus making Wheel immutable from Axis point of view.
Well, this solution is basic to start with. Ofcourse, you can think of whether to make Wheel final or not, cloning, serializable, etc. based on what level you want to make immutable.
Related
Consider this child class :
public class Circle extends BasicAreas{
public static void main(String args[])
{
BasicAreas ba = new BasicAreas();
Circle c = new Circle();
c.PrintCircleArea(ba);
}
void PrintCircleArea(BasicAreas ba)
{
System.out.println("Area of circle is : "+areaCircle(3.14));
}
}
and the parent class :
class BasicAreas{
double areaCircle(double radius)
{
return 3.14 * radius * radius;
}
int areaSquare(int side)
{
return side * side;
}
int areaRectangle(int len, int breadth)
{
return len * breadth;
}
}
Now, i am pretty well confused about this... :
System.out.println("Area of circle is : "+areaCircle(3.14));
When i extend a super-class...i can access the methods of that class without using an instantiated object like above....but
when i do not extend a class, i can access its method using an object like :
System.out.println("Area of circle is : "+ba.areaCircle(3.14)); /* "ba" being object */
So my question is that when should i prefer using objects and when to use extend to access other class methods...and whats the difference between them on basic level??
learning java...so please go easy...i know the question is pretty dumb, but there is no clear answer....i am also open to possibility that this question might be conceptually wrong too!!!
So my question is that when should i prefer using objects and when to use extend to access other class methods...and whats the difference between them on basic level??
the inheritance represents a is-a relationship. but the composition represents a has-a relationship. you can choose any of these two to solve your problem but to make a good design it is important to choose between the right one.
so inheritance should be used only when a subclass is-a superclass. for example in the above example circle is a basicArea. Otherwise use composition.
you can see this article or plenty of others avaiable on net to find the differences between these two with example.
When your class is not in the inheritance hierarchy, then you should use object method. When you extend a class, then the child gets the method by default as if it is its own method. THis is because child class is susbclass of superclass. i.e. In your case, Circle IS-A BasicAreas.
When you do not extend the class, then you do not have access to method as long as you instantiate the object.
In both cases, you are accessing the methods with objects.
When i extend a super-class...i can access the methods of that class
without using an instantiated object like above
This is wrong.
In the first case, you are accessing areaCircle() method on instance c.
When A class extends a class it can access the methods in super class i.e
double areaCircle(double radius)
in your case and when you are writing
System.out.println("Area of circle is : "+areaCircle(3.14));
this statement you are actually using object(this) for accessing this method the only point here is you are not creating this object.
this statement will be interpreted like this
System.out.println("Area of circle is : "+this.areaCircle(3.14));
so you always need object to access a method until it is not static. Because you can access static methods directly with class name.
I'm programming some kind of board game containing robots, items and such.
At one point, I need to get the energy value of a robot or an item that can have energy. The way this is programmed is that each robot and each item having energy have an EnergyContainer class as a field (to prevent code redundancy) and an energy Value class.
Now, basically, I call a method evaluate() that receives an Element. Element is an abstract class which robot and items extend. Not all elements have energycontainers. If possible, I need to call the getEnergyContainer on this element, but only if it is an element that has it of course.
I can think of a couple solutions: using a lot of instanceOf and then casting. So asking for example, if the element is instanceof robot, cast element to robot and call getEnergyContainer on the element. This has as clear disadvantage that I need to do this for every energy having subclass of element.
Second solution is defining an interface containing only a getEnergyContainer method and make all energy having classes implement this. The only purpose for this interface is then to facilitate the one method and it would be nearly empty.
Unless anybody has a better idea, what is the "best" solution? Nearly empty interfaces are used as Marker interfaces I think, but this it is one and only purpose so I'm a bit inclined against it.
If possible, I need to call the getEnergyContainer on this element, but only if it is an element that has it of course.
Why would you not want to call it on an element that doesn't have an energy container? If it doesn't have an energy container, either return a reference to some "null object" implementation of EnergyContainer, or return a null reference. It depends on what you want to do with it later - if you can easily implement some sort of "neutral" energy container, then the null object pattern is the simplest approach. Otherwise, just:
EnergyContainer container = element.getEnergyContainer();
if (container != null) {
// Use the container
}
There are no doubt those who would argue that this is in some senses "impure" - but it's almost certainly simpler than most alternatives.
The best solution would be to put the getEnergyContainer() method in one of the super classes of all energy containing elements the overriding this method in each elements class. You can make this method abstract to ensure its over-ridden. your super-class for this could be Element because you said: Element is an abstract class which robot and items extend.
Given your class hierarchy use composition with an Interface to provide default EnergyContainer behaviour
abstract class Element {
EnergyContainer ec = new EmptyEnergyContainer();
int getEnergyValue() {
getEnergyContainer().getValue();
}
EnergyContainer getEnergyContainer() {
return ec;
}
setEnergyContainer(EnergyContainer container) {
this.ec = container;
}
}
class Robot extends Element {
public Robot() {
this.ec = new ActiveEnergyContainer();
}
}
class Item extends Element{
public Item() {
this.ec = new ActiveEnergyContainer();
}
}
class Brick extends Element{
// will have a EmptyEnergyContainer by default
}
The Interface hierarchy for the EnergyContainer is like this
interface EnergyContainer {
int getValue();
setValue(int value);
}
class EmptyEnergyContainer implements EnergyContainer {
#Override
int getValue() {
return 0;
}
#Override
setValue(int val) {
throw Exception("Can not charge an empty container");
}
}
class ActiveEnergyContainer implements EnergyContainer {
int value;
#Override
int getValue() {
return 17 + 3; // calculate the value
}
#Override
setValue(int val) {
this.value = val // or do some funky calculation
}
}
At runtime you are able to set new EnergyContainer types for your objects. If you have multiple parent classes like Element then you will have to follow the same pattern of adding the default behaviour to the abstract parent and override as required.
Having the default behaviour return a sensible default value for getValue() will help you not have to use instanceof all over the place.
Potential improvements to this code would be to introduce
AbstractFactory pattern for creating the various EnergyContainer
variants
Including a hasEnergy() method to make your code more readable rather than checking for a value == 0
Make Element implement an Interface if other similar parent classes will include simlar methods
public abstract class Figure
{
private int offset;
public Figure()
{
offset = 0;
}
public Figure(int theOffset)
{
offset = theOffset;
}
public void setOffset(int newOffset)
{
offset = newOffset;
}
public int getOffset()
{
return offset;
}
public abstract void drawHere();
/**
* Draws the figure at lineNumber lines down from the
* current line.
*/
public void drawAt(int lineNumber)
{
int count;
for(count = 0; count < lineNumber; count++)
System.out.println();
drawHere();
}
}
In this class, it handles the figure for creating a tree. I am trying to turn it into a normal class by simply giving a body to the abstract method. I noticed that when I remove the abstract tags, it still works perfectly normal. But my question is, if I want to make the class non-abstract, through what means would I go through to do this?
This class is extended upon by 2 other classes and then it has the main class. Do I have to go through and modify those too?
You shouldn't be altering Figure; you should be extending it.
This class is extended upon by 2 other
classes and then it has the main
class. Do I have to go through and
modify those too?
All the more reason to not alter Figure: you'll break the rest of the code.
You should not be modifying anything. Create a new class that extends Figure and override the abstract drawHere() method with the behavior you want.
When you have an abstract class,
abstract class AbstractCar {
float maxSpeed;
Driver whoIsDriving;
AbstractCar(float ms, Driver d) {
maxSpeed = ms;
if(!validateDriver(d)) throw new InvalidDriverException();
whoIsDriving = d;
}
abstract boolean validateDriver(Driver d);
}
You can define the behavior separately for various conditions by extending and defining the abstract methods in question.
class CrappyCar extends AbstractCar {
boolean validateDriver(Driver d) {
return d.hasLicense() && d.hasInsurance();
}
}
class ExpensiveCar extends AbstractCar {
boolean validateDriver(Driver d) {
return d.hasLicense() && d.hasInsurance() && d.hasGoodJobInCaseHeMessesUpMyCar();
}
}
If you want a non-abstract class, then you must not declare it with the abstract modifier (i.e. just public class Figure). There shouldn't be any need to modify any derived classes (so long as they themselves are not abstract).
Technically speaking, in order to make an abstract class non-abstract you have to:
Provide implementation for all abstract methods
Since you now have a valid implementation of everything define, remove all abstract tags
There is no need to modify anything in inheriting classes (assuming they are non-abstract theirselves) because they already provide an implementation of all the abstract methods of their parent & are free to override any method they wish.
Whether or not you should make your class non-abstract is another point of discussion.
You are correct that removing the abstract keywords and implementing the abstract methods makes the class non-abstract.
However, you normally do not want to turn the class itself from abstract to non-abstract. A class is not abstract until you add this keyword, so you (or someone else) apparently had a reason to make sure it's not a normal class, but an abstract one.
If you think about it at a very high level (far from Java), then a "Tree" is something you know how to draw. Similarly, you could imagine a subclass "Circle" for which you know what a drawing shoud look like. For the very generic "Figure", however, you have no idea what it means to draw it.
This is the idea of why the actual drawing is left abstract in your Figure class. Hence, you should not make Figure non-abstract, but instead focus on the classes that extend from it and make those non-abstract, by implementing all abstract methods from Figure. In your Tree class, you know what drawHere should do, so implement it there to print a tree. In another class, like Circle you implement it differently, but it never really makes sense to implement it in Figure, where you have no idea what to draw.
You can declare a method body for drawHere() (presumably empty, since, as #Frank pointed out, you can't really have any idea about how to draw a Figure) and remove the abstract modifiers. Then you will have a concrete class. That means someone could create a new Figure(). This won't be either of the two subclasses you now have, just a Figure.
If such an object (that does nothing when it is called upon to drawHere()) would not be useful (and, in particular, if you would consider it an error to have such an object), then you should keep the class abstract. This reasoning applies even when you can define an implementation for every method.
If a class is made abstract you can give body to all the methodes or none of these but if any class is extending abstract class it must implement all the methode which is only being declared.
Let's say I have an object of the class Car, with like 30 variables ranging from top speed to color. I want to make a MyCar object (class MyCar extends Car) that is basically the same thing except it stores some more information.
It is not possible for me to create MyCar objects right away (since out of thousands of Car objects only a few will become MyCar objects), unless I leave the additional fields blank, but that doesn't seem too professional. And neither does creating a constructor which takes 30 arguments, or setting 30 arguments through method calls.
So, is there any way to easily inherit all the variables from a superclass object?
PS: My program is not about cars, but I figured it would be an easier example.
EDIT
Thanks for the replies. They are all helpful for my program, but not for this particular problem. Builders don't seem beneficial because these cars of mine don't have default values for their variables. Every time a car is made, all the variables are filled out (which is needed to construct a sort of "fact-sheet").
Envelopes are an interesting design, but still require me to copy all the variables in the subclass constructor. I was hoping there would be a way to circumvent this. Templates would also require me to copy all the variables one by one.
In my program the subclass acts as a sort of "wrapper class" in a search engine. The subclasses are the same as the normal cars, but they have a "ranking score". My program is designed to display regular cars, and by extending those I can easily display the subclasses and order them by score at the same time.
I have to create new objects anyway, because multiple searches can be performed on the same list of cars. So editing variables in the original cars was not an option.
Maybe there is a better solution to this problem, but for now I guess I'll have to pass the superclass object into the constructor and copy all the variables there.
Thanks for the help!
PS: I'm just thinking, perhaps I could throw all the variables into a HashMap. That way I could access them by using .get(varname), and I would only have to pass one HashMap variable into the subclass. Downside is I would have to cast a lot, since the vars are a mixture of Strings, ints, doubles etc. What do you think, is it acceptable coding style?
Effective Java 2nd Edition, Item 2: Consider a builder when faced with many constructor parameters
And neither does creating a
constructor which takes 30 arguments,
or setting 30 arguments through method
calls.
If you are facing a constructor with too many parameters then you might want to have a look at: The Builder Pattern.
The idea is to set only the field you want/know into the builder, without bothering with the optional ones, or ones that you'd want to use default values, then calling build() to construct the actual object. See the Java examples in that article.
Once you have setup that pattern, you can construct Cars this way (notice the clean structure):
Car car = new Car.Builder(required_param1, required_param2)
.color(RED) // optional params
.topSpeed(300)
.zeroToHundred(2)
.build();
You can add a constructor that gets a Car object and copy the values from the Car to the new MyCar.
It is not possible for me to create MyCar objects right away (since out of thousands of Car objects only a few will become MyCar objects),
So, you'll have lots of objects of Car type, a few of which you'd like to, at runtime, "promote" to SpecialCar type?
Do SpecialCars have exactly the same interface as Cars?
You might want to read up on Coplien's Envelope-Letter Pattern, it's a way of "changing" object type at runtime. The object doesn't really change type, of course; instead, a different "Letter" goes into the existing "Envelope". The Envelope is the handle that other code references, but method calls on the Envelope are delegated to the Letter:
class CarEnvelope { // an envelope
Car c ; // the letter
CarEnvelope( Car c ) { this.c = c ; }
int someMethod() {
return c.someMethod(); // delegate
}
void promoteToSpecialType() {
if( ! c.isSpecialCar() ) {
c = new SpecialCar( c ) ;
}
}
class Car {
Car() {}
int someMethod() { do Car stuff }
boolean isSpecial() { return false; }
}
class SpecialCar extends Car {
SpecialCar( Car c ) { /*copy c's attributes...*/ }
int someMethod() { do SpecialCar stuff}
boolean isSpecial() { return true; }
}
CarEnvelope c = new CarEnvelope( new Car() ) ;
// do stuff with c
c.someMethod(); // indirectly calls Car.someMethod();
// promote
c.promoteToSpecialType();
c.someMethod(); // indirectly calls SpecialCar.someMethod
OP here.
I understand that this looks like laziness. But I already have it working by manually copying 30 variables in the constructor. Not that big of a task, I know.
The thing is, I have been taught to code with style. When I see mindless code blocks that look like copypasta my instincts tell me that there is probably a better way. So my desire to learn and strive for perfection has driven me here.
But if there really is no other way than to copy the variables (or override all the get&set methods) then I don't have to look any further.
Needless to say, all the replies in this topic have given me new insights. Thanks guys.
I have a feeling that what you are looking for is the notion of a template; e.g.
public class Car {
private final int attr1;
private final int attr2;
...
public Car() {
super();
}
/* copy constructor */
public Car(Car template) {
this.attr1 = template.attr1;
this.attr2 = template.attr2;
...
}
/* setters and getters */
}
Then ...
Car myTemplate = new Car();
myTemplate.setAttr1(3);
myTemplate.setAttr2(11);
...
Car car1 = new Car(myTemplate);
car1.setAttr1(4);
Car car2 = new Car(myTemplate);
car1.setAttr1(5);
I don't get it. What's wrong with a regular inheritance?
class Car {
private int attributeOne;
.....
private boolean attrbuteThirty;
public void methodOne(){...}
...
public void methodThirty(){...}
}
And then just subclass it:
class SubCar extends Car {
private int extraAttribute;
}
All the 30+ attributes and methods are already inherited, that's what the extends is all about.
If what you need is to create a new object based on the data of an existing one, but you're resisting to code it! ( ¬¬ ) , then you may just create a small script to create the code for you. It's very easy. You copy/paste the generated code and you're done.
If you don't want to do it, because you don't want to duplicate the data, you may override interesting methods, and delegate the code to the original, that's what the Decorator design pattern is all about:
class SubCar extends Car {
private Car wrapped;
private String extraAttribute;
public SubCar( Car original, String newAttributeOne ) {
wrapped = original;
this.extraAttribute = newAttributeOne;
}
public void someMethod() {
wrapped.someMethod();
}
public String getName() { return wrapped.getName(); }
... and so on
// new method
public String extraAttribute() { return extraAttribute; }
}
That way you won't duplicate the data, but just decorate it.
We can create an interface ICar that has all the getters and setters for all the 30 columns.
Car can implement ICar and can contain all the 30 fields with their corresponding getters and setters.
MyCar can also implement ICar and can use composition. It exposes Car's methods as delegate methods (which can automatically be generated in an IDE like eclipse)
public interface ICar {
// getter and setter methods
}
public Car implements ICar {
private String color;
// getters and setters for each of the fields
}
public MyCar implements ICar {
private Car car;
public MyCar(Car car){
this.car = car;
}
public String getColor() {
return car.getColor();
}
}
All consumers could then use the ICar interface for their manipulation. Will that work?
I am currently developing a little platform in Java and I wrote my own game engine for it called Bonsai. Now I'm asking myself the question "Did I overuse statics?".
On the one hand it's very convenient since I don't have to keep a reference to the game instance in each class like the map or the player. On the other hand... I have already had to strip out applet support since it was very buggy with all that static stuff in there.
So my question is, since you may be much more experienced Java programmers than I, should I get rid of all the statics? And if yes, what would be an effective approach to get to something like this:
public void draw(Graphics2D) {
if (this.game.time() > this.timer) {
this.game.image.draw(this.tiles[this.game.animation.get("tileAnim")], x, y, null)
}
}
instead of:
public void draw(Graphics2D) {
if (Game.time() > this.timer) {
Image.draw(this.tiles[Animation.get("tileAnim")], x, y, null)
}
}
or even worse in the map editor:
public void control() {
if(this.map.game.input.keyPressed(...)) {
this.map.game.sound.play(...);
}
}
EDIT
Based on the answers I decided to have an GameObject class which provides wrapper methods for each component. Map, player etc. then subclass from it, this way I all the this.game calls are hidden behind the scens an it still looks nice on the frontside:
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();
}
}
Now the code looks like this:
public class Player() {
public Player(Game g, int xpos, int ypos) {
super(g);
// do other stuff
}
public void jump() {
// jump code
Sound().play("jump");
}
}
Or is this even worse Java?
EDIT2
Ok I'd already run into problems using method calls the compiler is giving me errors since it can't find methods of my subclassed Game in the original one, i think I'm jsut gonna use plain fields here.
EDIT3
Ok my GameObject class now looks like this, everything works fine again and I can reimplement that applet support :)
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;
}
}
First of all.
You don't have to get rid of all your static code just because that would make it better on "paper".
You really have to understand what the difference is between instance code (non-static) and class code (static)
static code (class methods/attributes) is used when the methods/attributes do no need an instance of the class to work. A very good example is the image draw method: Image.draw()
instance methods/attributes are useful to keep state of a given object which must be kept separate from data in other objects.
For instance, if you have Player class in your game and you have two instances player1 and player2 it makes sense each of them to have their own score:
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 );
Instead of having to create artifacts to keep each player score (like putting them in arrays where each index is an attribute and make that array static etc. etc.)
Secondly
You may reduce the constructs you mentioned object1.atr2.other.next.etc by assigning to objects appropriate attributes and performing encapsulation in the right way.
If a object b needs to access the N'th element of another a it is likely that said attribute belongs to the object b instead of a or probably that object a should provide a method to avoid exposing it's internals.
It even makes the code easier to read:
ie.
public void draw(Graphics2D) {
if( this.game.needsDrawing() ) {
this.game.draw();
}
}
instead of:
public void draw(Graphics2D) {
if (this.game.time() > this.timer) {
this.game.image.draw(this.tiles[this.game.animation.get("tileAnim")], x, y, null)
}
}
Again, it depends on the situation, there might be scenarios where you don't need an instance (again, like the draw() utility method of Image)
Finally.
Instance methods allow you to use polymorphism while class methods do not (at least, in Java and other statically typed languages).
So, you may benefit from using runtime delegation and polymorphism if your code is instance code. Take for instance the State pattern you can't use it if all your code is static, but you can with instance code:
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...
}
}
And once again, only if this make sense in terms of object orientation, like does the object have attributes whose data is required? If not it may be good to keep that section of code static.
All these concepts (encapsulation, polymorphism, abstraction, inheritance, etc) are the very nature of OO technology and covered in OOA/D while they may seem like syntactic sugar (and most of the times they are) your experience will tell you when you should have something as class code and when as instance code.
static exists as a semantic tool like any other. When something is static, that has meaning to what the class is trying to model. In your case, you're effectively using static to create global storage and you've apparently run into some of the problems the prompt the general rule of globals being "bad."
If the behavior of your static interfaces is forcing your hand on design issues and implementation issues in ways you don't want it to (like your applet support, e.g.), then yes, it's a problem and you should consider refactoring into a more appropriate design.
Should you get rid of all the statics? Maybe. If it's impossible for more than a single instance of a particular object to exist at any one time, and you're willing to handle the cost of synchronizing access to the object, then maybe something can remain static. I don't see anything in your example that I would absolutely keep static based on my guess of what they do, though.
(Regarding your apparent distaste for the chained object references, you may want to look into the Law of Demeter and techniques that can bring code more in line with it. I don't think code should adhere to it strictly, but there should generally be an attempt to keep the chained method calls somewhat short.)
In my view, using statics to share some global state instead of having to inject it into client classes makes code more difficult to test, reuse, hack, etc, because you are coupling those client classes to the class whose static members they are using.
Here's a contrived example:
What if, say, you come up with 2 different types of Game class and you want to benchmark them both.
Or maybe you want to extend your engine to run two completely different types of game (maybe a platformer and a shoot-em-up, who knows) and it just so happens you can do this by modifying Game and keeping all the other classes the same. (I said it was contrived.)
With all your other classes accessing static members of the Game class, you have to write 2 versions of your application, each with its own implementation of Game.
If you simply passed a Game object into every class that needs it, you can subclass Game and pass any sort of Game into the client classes that need it.
Excessive usage of statics usually hardens making changes to code and decreases its testability.
Consider replacing static objects with normal objects. You may pass them into constructor of your object. This way, they would be easily replaces with another implementation (real or mock/stub for testing). This technique is called dependency injection (DI).
E.g., you've passed to your app three objects:
gameTimer (extracted from Game class to make it less God-like)
image
animation
and saved it to fields. This way instead of
public void draw(Graphics2D) {
if (Game.time() > this.timer) {
Image.draw(this.tiles[Animation.get("tileAnim")], x, y, null)
}
}
you'll have
public void draw(Graphics2D) {
if (this.gameTimer.time() > this.timer) {
this.image.draw(this.tiles[this.animation.get("tileAnim")], x, y, null)
}
}
The difference looks subtle, but actually is significant, because your code will become more modular.
Each object has single responsibility and thus can be tested well.
If you'll implement another version of Animation class (Animation2), you'll need to make changes in your main() function only, not in the Animation class.
Single glance on your code shows which objects are used, no need to look for static methods calls.
My personal experience with statics is really two-fold. Firstly, I find that statics are an anti-pattern that often obfuscate and hide the fact that I have a problem with my design. If I find myself needing a static variable, I have to ask myself why. However, there are times when a static is needed, and in fact appropriate. In these cases, I attempt to isolate the pieces that are truly global to the program, and place them in their own singleton class, rather than a static variable somewhere. Although it may just be semantics, making them a singleton keeps things a little cleaner in an OO sense in my experience.