I'm creating a monopoly game with different types of squares.
Square is the Superclass and PropertySquare is the Subclass.
I've created a loop that rolls the dice and moves the players to a different square. The squares are in an array list and I am able to call the superclass methods on them. However, even if the squares are set to more specific types (subclass of square), I cannot call the subclass methods on them.
This is how I have initialised the squares in a board class.
private static final ArrayList<Square> squares = new ArrayList<Square>(40);
squares.add(1, new PropertySquare("Old Kent Road", 1, 60, "Brown"));
board.getSquare(pos).getName());
getName is a method in the superclass square. However, even if the square is a property type, I cannot call the methods in the PropertySquare class such as getPrice();
How would I change this or be able to call the subclass methods?
I assume board.getSquare() returns a Square, and Square doesn't have any getPrice() method, so you can't call getPrice() over an object declared as Square, even if the instance is actually a PropertySquare (a.k.a. polymorphism). To do so, you have to first cast to the specific subclass. For example:
final Square square = board.getSquare(pos);
if (square instanceof PropertySquare) {
((PropertySquare)square).getPrice();
}
You should use Generics with the ArrayList.
If your list only contains of type PropertySquare, do it like this:
private static final ArrayList<PropertySquare> squares = new ArrayList<>(40);
squares.add(1, new PropertySquare("Old Kent Road", 1, 60, "Brown"));
Then the list will returns objects of type PropertySquare.
If the list can contain any type of square, do it like this:
private static final ArrayList<Square> squares = new ArrayList<>(40);
squares.add(1, new PropertySquare("Old Kent Road", 1, 60, "Brown"));
Square sq = squares.get(0);
if(sq instanceof PropertySquare){
PropertySquare pSq = (PropertySquare) sq;
//now you can use any method of PropertySquare
}
The problem in your code is that your object is of type Square and does not know anything about the methods of any subclass. So you have to do a type cast.
you could handle the landing square in a group of ifs like:
if (square instanceof PropertySquare) {
((PropertySquare)square).getPrice();
}else if(square instanceof PrisonSquare) {
//do nothing
}//etc..
Your declared ArrayList is bound to Square meaning you will have a collection of Square objects and a Square reference when interacting with any items despite at run-time it being an instance of a subclass. This is known as polymorphism.
Due to the fact that the references are of type Square the only methods Java knows about are those declared in Square and any other inherited methods. For you to be able to call methods of a subclass you would need to check whether the reference is pointing to an instance of PropertySquare and then down-cast the reference to PropertySquare. You're then saying, it's okay I know its an instance of PropertySquare so I can safely call the getPrice() method declared in PropertySquare.
if (square instanceof PropertySquare) {
((PropertySquare)square).getPrice();
}
Alternatively you can look at the instances class name:
square.getClass().getSimpleName(); // Would just give you PropertySquare
square.getClass().getCanonicalName(); // Would give you the fully qualified name e.g. com.foo.bar.PropertySquare
For more info:
https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html
NB: I'm going to answer this in the more generic sense, I realise that not all Monopoly Squares have a price... But the problem itself, in code, can be solved in two ways.
If all of your items have a price, you probably want to use an "Abstract" base class.
You then put in the methods in the superclass as
protected abstract int getPrice();
and implement it in your subclass.
So you could have subclasses such as undevelopedSquare, propertySquare, gardenSquare etc.
However, in the case of Monopoly, if only the propertySquare instances have getPrice, you should use
if (square instanceOf PropertySquare) {
price = ((PropertySquare)square).getPrice();
}
NB2: You also have "utilitySquare"s such as the Waterworks, which would have different properties alongside the price (you can't build a hotel on a utility even though you can buy it).
So in this case, maybe Interfaces would be more appropriate such as:
interface PlayableSquare -> Generic square things, you can land on one for instance
interface SaleableSquare -> has pricing etc
interface BuildableSquare -> can build hotels
And then have your generic as
private static final ArrayList<? extends Square> squares
The PropertySquare would then be:
public class PropertySquare extends AbstractSquare implements SaleableSquare, BuildableSquare
where the Abstract class implements "PlayableSquare". Although that may be a step too far as it would almost just be a marker interface.
you can use instanceOf to check for each interface implementation, i.e. if a Utility has a different method you wish to call.
Related
I am currently reading Herbert Schildt "Java the Complete Reference" and there he has used a term "Dynamic method resolution" and has provided a little explanation, but i am not getting the full import of it so asking for help in this forum.
while discussing 'interfaces', what he is saying is, dynamic method resolution helps in resolution of method name at run-time and it is achieved by declaring a interface variable and using it to refer to a class object. i.e
interface i = new object();
now what is so unique about it? you can use a class variable also to refer to the same object like:
class c = new object();
so, what is the use of interface here? and why introduce this new term "dynamic method resolution"??
Second he makes a point by saying: " when we use an interface variable to refer to instance of any class, and when you call a method through these interface variables, the method to be executed is looked up dynamically at run time allowing classes to be created later than the code which calls method on them. The calling code can dispatch through an interface without having to know anything about the callee".
Now, Anything dealing with objects has to be in run-time as objects are created at runtime, Now, I dont understand what he meant by "allowing classes to be created...on them".
Any help will be appreciated.
Here is a little example:
public interface Animal {
public String sound();
}
public class Cat implements Animal {
public String sound() { return "meow"; }
}
public class Dog implements Animal {
public String sound() { return "woof"; }
}
public class Test {
public static void main(String[] args) {
Animal a;
if (args.length > 0)
a = new Cat();
else {
a = new Dog();
}
System.out.println(a.sound()); // prints "MEOW" or "WOOF"
}
}
What is so unique about it? You can use a class variable also to refer to the same object
Yes. But you cannot use a single class variable to refer to an instance that can be an instance of any class that implements the interface.
In Test class, if I declared a to have type Dog or Cat there would be no way to get the code to compile. Without the ability to declare Animal a, I would need to have two distinct variables, and two separate print statements.
This is what dynamic method resolution (aka polymorphism) gives you.
To understand his second point:
public class Test2 {
public static void main(String[] args) {
Animal a = PetShop.buyPet(args);
System.out.println(a.sound()); // prints "MEOW" or "WOOF"
}
}
The Test2 class will work with my Cat and Dog class from above. It will also continue to work without recompilation if in 3 years time I implement a Goldfish class and modify my PetShop class to stock aquatic pets. And indeed, it is even possible to implement the PetShop class so that it doesn't need to be changed or recompiled to support other kinds of pets.
Now, these examples are clearly not practical. However, the Java features that they illustrate are useful in real Java applications. Indeed, a program as simple as a classic "hello world" program relies on dynamic method lookup.
dynamic method resolution means Single method which can be applied to solve multiple problems. Ex: Consider Shape is an interface and has method name draw.
you have Rectangle and Circle classes implements Shape Interface. So when you create instance of Rectangle object and call the draw method will draw the Rectangle shape.. In other case you can instantiate Circle instance and call draw method to draw Circle...
In interface you may assign child object in the parent container.
Ex: Shape p = new Rectangle();
in this case it will create the instance of Rectangle and assign it into Shape p..
but from the Shape p object you can call only the draw method... you can not call other methods in the Rectangle Object since its assigned to parent interface and parent has only draw method.
As I proceed through my online tutorial, I came across this lesson. I have an interface and two classes that implements that interface.
public interface Payable {
double getPaymentAmount();
}
and
class Invoice that implements the above interface Payable
class SalariedEmployee that extends an abstract class Employee which implements Payable interface.
A test class that contains the main method to test this.
Now in the test class, when creating an array of objects, the type of object was referred to as Payable[] rather than SalariedEmployee[] or Invoice[], like
public static void main(String[] args) {
Payable[] payableObjects = new Payable[4];
payableObjects[0] = new Invoice("0000", "abc", 1,2);
payableObjects[1] = new SalariedEmployee("test", "user", "000-000", 35);
Is this because all the classes implements the interface Payable[] ?
If an interface is defined at the top level hierarchy, is it always possible to create objects of all the classes that implements that interface?
Your question title is not grammatical, but the word choice suggests there's a subtle misunderstanding of concepts going on.
You can only create a class as that class. That is, you can't write new Payable and somehow expect there to be any Invoice or SalariedEmployee objects being created.
But you can make a reference to a Payable point to any object that implements Payable. That's pretty much the fundamental idea of subtype polymorphism.
What's going on in the example is that an array of four Payable references is created. These references don't yet point at anything (they're null) and there are no Invoice or SalariedEmployee objects around yet, only the array object.
Then, the code creates two objects and assigns them to two of the references. This works the same as if the array elements were independent variables. (Almost, but the difference is due to array covariance, which isn't important at this point.) In particular, the result of the new operator has the type Invoice in the first case, not Payable. You can assign the Invoice to the Payable reference, but the conversion happens at assignment, not at creation.
So technically, the answer to your title question is "no, objects are always created as the type you specify in the new expression, but you can convert the references afterwards".
for your first question: yes, you would get a compiler error if it wasn´t the case.
for the second case, take the List or the Map as an example. Look at the following example. We declare a list but depending on the the flag, we want the this specific List to act different, since it represents a different class
public class BookList{
List <String> list;
public BookList(boolean flag) {
if(flag) {
list = new ArrayList<>();
} else {
list = new LinkedList<>();
}
}
}
Since we declared it just as List we are able to assign different type of lists that implement this interface. You could change the usecase of this class very simple, while you are still able to acces every method that is provided by the interface.
That´s what your array of Payable is doing aswell. You want to assign different types of classes into this array, which all implement this interface.
This would make it more easy, to create methods for this specific interface. Take a summing method as an example for your case.
public int sumPayable(Payable[] payables) {
int sum = 0;
for(Payable p : payables) {
sum += p.getPaymentAmount();
}
return sum;
}
In this case, it wouldn´t matter what the actuall class of each of this classes that do implements Payable is, since you could simply pass an array, like you did create, to this method.
I'm somewhat confused in understanding how polymorphism actually works. At most, I understand that a superclass reference variable can refer to a subclass object reference, but I can't use that reference variable to access any of the subclasses fields and methods. Take for example this sample program:
public class Game
{
public static void main(String[] args)
{
Human hero = new Knight();
hero.stats();
}
}
class Human
{
public void stats()
{
System.out.println("HP: 10 STR: 25.");
}
}
class Knight extends Human
{
public void skill()
{
System.out.println("Sword master");
}
public void weapon()
{
System.out.println("Sword");
}
}
From the sample program above, the only method I can call using the reference variable, hero, is the one declared within the class Human, but I have no access to any methods declared in the Knight class.
If I were to include the following whoAmI() method in both the Human and Knight class, the reference variable then refers to the subclass overriden method:
{...
hero.whoAmI() // calls the method declared in the Knight class
}
class Human
{
public void whoAmI()
{
System.out.println("Just a regular human");
}
}
class Knight extends Human
{
public void whoAmI()
{
System.out.println("A mighty knight");
}
}
While I do understand why the overriden method whoAmI() is called instead of the superclass' method, since the JVM (correct me if I'm wrong) sees that the reference variable contains a reference to a knight object, why can't I access any of the methods declared within the Knight class using the reference variable?
Human hero = new Knight();
You defined your hero to be a class Human. Therefore, you will only inherit those properties that are available to its parent class.
If you define your hero as a Knight, then you will have access to both Human and Knight properties.
Knight hero = new Knight();
a few nitpicking: better declare your properties private, and use a getter/setter.
Hope this helps.
Because, it breaks the contract.
Let's assume (just to understand the why) that Java allows you to call a Knignt class method on a Human class reference and you publish a public method like
public void doHumanThings(Human being) {
...
// but somewhere inside the method you call
being.doKnightThings();
...
}
This breaks the contract because other classes can't simply pass a Human object like
Human onlyHuman = new Human();
someObj.doHumanThings(onlyHuman);
That's because if they do, your code breaks at runtime when calling
onlyHuman.doKnightThings(); // ERROR!
because All Humans cannot be Knights.
So, although you've declared to the rest of the Java world classes (with a public method in a public class) that you expect a Human object, you're breaking the contract by expecting it to behave like a Knight which the other client classes may not be even aware of.
You can't simply assume that a Human reference will always point to a Knight object. The only way you can enforce that is by declaring the reference of type Knight itself.
However, if a method implementation wants to mostly make use of the parent class behaviour but add or adapt in case a subclass object is received, then an explicit downcast following an instanceof check can be performed as
public void doHumanThings(Human being) {
being.doHumanThings();
...
// Is this Human a Knight too?
if (being instanceof Knight) {
Knight iAmAKnightToo = (Knight) being;
// OK. Using a Knight reference now.
iAmAKnightToo.doKnightThings();
}
}
Think it this way
Knight hero = new Human();
Why this is wrong ?
Since accessible/visible methods depend on the type of reference variable hero.
So all child methods can be called logically but technically u are not holding the object of child class so u cannot call the child methods.
Similarly u are holding a base class reference
Human hero = new Knight();
The methods that are visible/accessible depends on the type of reference variable in which you are holding the object and not on the object.
So if you change it to
Knight hero = new Knight();
All the methods become accessible (base class and child class).
why can't I access any of the methods declared within the Knight class
using the reference variable
Because at compile time, compiler only knows about the reference used, so only methods available in the reference type class are available.
Poplymorphism is also called dynamic binding because it is decided at the run time depending on the object, which class method will be called.
You can only access the methods from the type of the left side of the declaration. Java sees the object 'hero' as a Human not a knight. This helps with type safety in iterators and the like (more advanced than this question I think). This is a safety feature that ensures certain methods are implemented but can also be overridden or not.
So only the methods in the left hand declaration are available. It may seem annoying now but in more advanced polymorphic problems this is a very nice type safety.
Every class and every interface defines a contract. Contract is defined by public methods (very simplified).
Contract means what methods you can call on the object extending a class or implementing an interface. If you store an object (Car) to a reference of different type (Vehicle):
Vehicle v = new Car();
You are basically saying treat the car as a vehicle. Once you say that you are using the contract of the Vehicle and not the car.
That means you can only call methods defined in the Vehicle and not the new ones in Car.
Human hero = new Knight();
Human = Referance Type , hero= Reference variable ,
new Knight() = Object Type
if you call a overriden method ; Object Type decides which method can be called.
if you call a non-overriden method ; Reference type decide which method can be called.
A simple question on Java class
I want to create my class with my own add method which adds an object of a different class.
For eg if my class name is Weapon, I want to create an add method like void add(Gun gun) (Gun being one of my other classes for example)
This would be just like creating your own collection maybe??? if I am not wrong? Like list.add() method, I want to implement my own add method for the Weapon class
So when I instantiate an object of my weapon class, it should be like
Weapon w = new Weapon(new Gun( ... .. constructor parameters) )
Also I would like to have variants of my add methods. Like a different add method with different parameters like void add(Weapon weapon) ( creating an method to add your own class object )
So I am not sure if this is similar to implementing a collection?? And if it is how do I achieve it? Do I have to extend another class for this?
Apologies if my question confused anyone! :)
List<Object> weapons = new ArrayList<Object>();
weapons.add(new Sword());
weapons.add(new Gun());
try this.
You don't necessarily have to do a new Gun() when you instantiate. You can just do the following:
class Weapon
{
private Gun gun;
public Weapon()
{
gun = new Gun(); //etc.
}
//add more methods here. You can use gun.function() to invoke any functions
}
As for using a Weapon object, just declare public methods in the Weapon class and then invoke them in your methods.
For example, the add() function:
class Weapon
{
...
public int val() { return 0; } // don't know, some random method.
}
Then on a different file:
int add(Weapon w)
{
return Weapon.val() + 1111; //perform something here
}
I hope this answers your questions, it was a little bit unclear :|. Comment if you need more help.
Your question is a bit unclear to me, but I'll try my best.
If you want to have a List of Weapon, then you need to use inheritance. In your example, A Gun is-a Weapon. Therefore, you can do class Gun extends Weapon. Then, let's say you're using an ArrayList, you would instantiate it like:
List<Weapon> weapons = new ArrayList<Weapon>();
You can now call add with a Gun, or any other sub-class of Weapon like so:
weapons.add(new Gun()); //or
weapons.add(new Cannon());
If you actually need to add a Gun to a Weapon (Which doesn't really make sense...), you can use composition. See Shahar's answer for a more detailed explanation of this behavior.
Just to clarify, no matter what, I'm pretty sure creating a new Collection is not what you want to do here.
These are a lot of questions :-) let's enumerate them
creating a method called add() into an object makes this object a Collection? No. To be a Collection, a class must implement the interface java.util.Collection or implement any one of the subinterfaces or extend any of the subclasses that implement this interface. A list of them is available in the Collection javadoc - http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html
if I want to add an object into another, it must be via the constructor? e.g. new Weapon(new Gun())? Not necessarily. You can just create a Weapon w = new Weapon() and then add the Gun reference via a method such as w.setGun(new Gun()). Anyway, any constructor with one or more parameters must be declared explicitly in your class. Only the non-parameter constructor is available by default.
Now, let's suppose that you want to store a class Gun that is a subclass of a class Weapon. Then you first need to define the hierarchy between them, for example
class Weapon{
}
class WeaponWithBlade extends Weapon{
}
class Sword extends WeaponWithBlade{
}
class Knife extends WeaponWithBlade{
}
class Gun extends Weapon{
}
and then you want to store all these weapons in a Weapon collection.
since all of them are subclasses of the Weapon class, it's valid to do something like this
java.util.List<Weapon> weapons = new java.util.ArrayList<>();
weapons.add(new Sword());
weapons.add(new Gun());
notice that both List and ArrayList are collections (List is an interface and ArrayList is a concrete class that implements the List interface), parametrized to be collections of Weapons.
I hope this can help you.
Suppose the following classes are defined:
class Shape { }
class Circle extends Shape { }
class Rectangle extends Shape { } // 1
You can write a generic method to draw different shapes:
public static <T extends Shape> void draw(T shape) { } // 2
The Java compiler replaces T with Shape:
public static void draw(Shape shape) { } // 3
My Question is, if we define directly // 3 in our class then we still be able to pass Shape, Circle and Rectangle reference to method at //3. Then why do we need to write // 2 generic method with type parameter <T extends Shape> which is untimately going to be same as //3 ?
You can refer this link with same example : http://docs.oracle.com/javase/tutorial/java/generics/genMethods.html
You may or may not need it. You need it if your method has to deal with other objects of the type T that must match the type of T extends Shape exactly, for example:
public static <T extends Shape> void drawWithShadow(T shape, Class<T> shapeClass) {
// The shadow must be the same shape as what's passed in
T shadow = shapeClass.newInstance();
// Set the shadow's properties to from the shape...
shadow.draw(); // First, draw the shadow
shape.draw(); // Now draw the shape on top of it
}
Above, passing Shape would not be enough, because we wouldn't be able to make the shadow of the exactly same type.
In case when there is no such requirement, a simple Shape would be sufficient.
In this particular case, you don't need a generic method.
But you can do more in a generic method than call a dynamically linked method on its arguments.
For example, you might have a generic method that accepts and returns a collection of T elements. Parameterizing it by type allows you to use it on multiple collection types.
Other examples where generic methods are useful are in this Java tutorial.
In your example, //3 is indeed the same as //2. But in other usecases, generic type may be useful:
you want to return value from the method, of the same type as the argument
you have 2 or more parameters and want to set restriction that they must be of the same type
The difference is that the kind of polymorphism you are using.
In the generic case you are using parametric polymorphism while in the second one you are using polymorphism by subtype. Actually you first case uses both kind of polymorphism.
Now, they could be similar in some aspects but they are not the same. A practical example:
List<Shape> shapes;
List<T extends Shape> specificShapes;
You can see that in the first case, not having a type parameter, I can't manage a list of a specific subtype of Shape, I can only manage an eterogeneous list of shapes but I'm unable to force any specific one on it. So I don't have any compile time juice that forbids me from adding a Triangle and a Rectangle to the shapes.
class ShapeDecorator {
private Shape shape;
..
Shape get() { return shape; }
}
class ShapeDecorator<T extends Shape> {
private T shape;
T get() { return shape; }
}
Here is another example, in this case you could write a generic decorator which is able to return a type T without the need of any cast. This can be useful in many situations in which having the common ancestor as subtype is not enough.
The main interest is that you can restrict the usage of your method to a specific type of shape in different part of the code.
At some point you may want to parametrize it to draw only Rectangle and in another place only Circle and this will be checked at compile time even if, at runtime, you will pass something of type Shape