An add method to add objects in your custom java class - java

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.

Related

what is dynamic method resolution

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.

what is the benefit of making super class reference when we can do sub class reference

what is the benefit of dynamic binding over static one..
If we want to access the methods of sub class then we can make an object of the same with reference variable of sub class type…. what is the benefit if we want to call a method of sub class and using reference variable of super class type?
class Human{
public void walk()
{
System.out.println("Human walks");
}
}
class Boy extends Human{
public void walk(){
System.out.println("Boy walks");
}
public static void main( String args[]) {
//Reference is of parent class
Human myobj = new Boy();
myobj.walk();
}
}
O/p :Boy walks
In the above example
why do we need to use "Human myobj = new Boy();" instead we can use "Boy myobj = new Boy();"
My point is what is the use of assigning super class reference to sub class object.
I am really confused about this. Please help me..
You can use either,
Human myobj = new Boy();
or
Boy myobj = new Boy();
depending on what you want to achieve. If Boy had an additional method
playWithOther(Boy boy)
and the remaining code needs to call this method, than you have to use the latter version. If the remaining code doesn't need to call any Boy specific methods, then it's usually considered good practice to use the more generic super class. That way you indicate that the remaining code will work with any Human object, so a simple replacement of Boy with Girl
Human myobj = new Girl();
will work. You can find many examples for this, e.g.
java.util.List
java.util.ArrayList
java.util.LinkedList
In your code, you should generally define variables as java.util.List and then instantiate either one of the list implementations (or any other class, that implements the List interface). This approach allows you to change the implementation of the List interface at a single place were you create the List object. The rest of the code will not require any syntax changes if you use a different List implementation.

In Java polymorphism, can all the classes that implements an interface be created as that type interface?

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.

Subclass and Superclass methods

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.

Confusion about extended classes in Java

I am having some confusion about extended classes. I think the best way to explain what I want to do is with some skeleton code:
abstract class Player
{
public int solve()
{ // One method of solving problem
}
}
class otherPlayer extends Player
{
public char solve(int num)
{ //Different method of solving same problem
}
}
// I suspect this is a wrong way to create Player
Player first = new otherPlayer;
// Because this gives me an error...
first.solve(5)'
// And this uses the super class's method of solving problem
first.solve();
// I don't want to do this though...
otherPlayer first = new otherPlayer;
// Because I actually define the Players in a method
// that returns a type Player():
private Player genPlayer()
{ // Take input from keyboard
Player newPlayer;
if (specific set of answers)
newPlayer = new otherPlayer();
else newPlayer = new Player();
return newPlayer;
}
My understanding of extended classes is limited. If I say "TypeA var = new TypeB", and TypeB extends TypeA, it seems that var only has access to methods in the TypeA class. What does it do, then to say it is a new TypeB? Why is that even a legal way to instantiate a variable? And how would you recommend I restructure this program so I can make it work (I'd prefer to keep the method, so I don't have to make a mess every time I create a Player)?
I really just want to know how to create an extended class as if I were a person who knew what he was doing.
You need to do something like:
abstract class Player {
abstract void solve(int num);
}
class OtherPlayer extends Player {
void solve(int num) {
//...
}
}
That is, to call a method through variables of type Player, at least its signature must be declared on that class - and must be implemented in all subclasses. There is no way to call a method that may or may not exist in a subclass using a variable of the superclass type.
Imagine you could do this:
class Player {
// ...
}
class FooPlayer extends Player {
void solveInt(int num) {
// ...
}
}
class BarPlayer extend Player {
void solveString(String s) {
// ...
}
}
Player[] players = new[] {new FooPlayer(), new BarPlayer()};
// this is the sort of code you want to work
for (Player p : players) {
p.solveInt(123);
}
what's supposed to happen when the method is called on BarPlayer? As you can see, it doesn't make much sense to allow this.
While it's not very useful to do Player player = new FooPlayer() explicitly, it does let you not have to know which exact subtype of Player the value is. It's missing the point to look at the methods that are different between the subtypes - the point of polymorphism is that the same method (i.e. with the same signature) is implemented in a different way between the subclasses:
class Player {
abstract String greet();
}
class EnglishPlayer extends Player {
String greet() {
return "Hello";
}
}
class JapanesePlayer extends Player {
String greet() {
return "Konnichi wa";
}
}
The point of TypeA a = new TypeB() is programming to contract. It means you can change TypeB into any other type that extends TypeA and be guaranteed not to have to change any other line of your code.
first, you are getting an error in the instantiation syntax. It should be new otherPlayer(). Also classes should be capitalized in java.
I assume the code is within a method, otherwise it will not compile.
Finally, to answer your question why you extend a class, if otherPlayer had its own implementation solve() (no arguments) then which method would be called would depend on the instantiation you used, not on the variable type. In other words, first.solve() would call the method in otherPlayer, not in player.
extension is about superclasses and subclasses.
if typeA is a subclass of typeB, then you could say
typeA extends typeB, and typeA would inherit all of the methods of typeB
it only works one way, kind of like a child can inherit traits from their parents, but the parents don't inherit anything from the child
if you want a method in the subclass to behave differently than in the parent class, simply write a new method with the same name/parameters. subclass methods automatically override superclass methods. then, if you want to use the superclass version of a method, you can use the super keyword
Inheritance is something that happens when you extend a class, you need to figure out the common methods you want in your class and subclass and define any alternates in your subclass.
Check this out for more info: http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
you declared 'first' as a Player reference that is referencing an otherPlayer object. This is legal, but if you want otherPlayer behavior, you will have to typecat 'first':
((otherPlayer)first).solve(5)
First of all, you can't instantiate abstract classes, so you can't code newPlayer = new Player();.
Then, it's perfectly legal to write something like ClassA a = new ClassB(); as long as ClassB is a subclass of ClassA and ClassB is not an abstract class.
In the case you have a method in ClassB that overrides a method of ClassA, which one is called depends on the dynamic type of the object that is actually the type you used for instantiate that object, this is called Polymorphism. There is lot of material about this (Object Oriented Programming and Java) on the web, but I think a great place to start at, is the book Thinking in Java by Bruce Eckel, he offers the third edition for free at his site (http://www.mindview.net/Books/TIJ/).

Categories

Resources