Java - array of different objects that have the same method(s) - java

I am practicing inheritance.
I have two similar classes that I'd like to assimilate into one array, so I thought to use the Object class as a superclass since everything is a sublcass of Object.
So, for example I put T class and CT class into an array called all like so:
Object all[] = new Object[6];
all[0] = T1;
all[1] = CT2;
all[2] =T3;
all[3] = CT1;
all[4] = T2;
all[5] = CT3;
I skipped the declarations as thats not my problem.
My real issue becomes when I wish to call a function within the array utilizing a loop:
for (int i = 0; i < 6; i++) {
all[i].beingShot(randomNum, randomNum, AK47.getAccuracy());
}
The classes involved with T and CT respectively both have the beingShot method, which is public.
Eclipse advises casting them as a quick fix. I'm wondering if there is any logical alternative other than creating my own Object class that holds the beingShot method, or adding this to the class of Object, although I feel either of these choices would cause more problems in the long run.
Thanks!

If both classes implement the same method(s), you should consider creating an interface.
Interfaces are very powerful and easy to use.
You could call your interface Shootable.
You can create an array of different objects that implement Shootable and treat them all the same.
// Define a VERY simple interface with one method.
interface Shootable {
public void beingShot();
}
// Any class that implements this interface can be treated interchangeably
class Revolver implements Shootable {
public void beingShot() {
System.out.println("Revolver: firing 1 round");
}
class MachineGun implements Shootable {
public void beingShot() {
System.out.println("Machine Gun: firing 50 rounds");
}
}
class HockeyPuck implements Shootable {
public void beingShot() {
System.out.println("Hockey Puck: 80 MPH slapshot");
}
}
class RayBourquePuck implements Shootable {
public void beingShot() {
System.out.println("Hockey Puck: 110 MPH slapshot");
}
}
class OunceOfWhiskey implements Shootable {
public void beingShot() {
System.out.println("Whiskey Shot: 1 oz down the hatch...");
}
}
// You can declare an array of objects that implement Shootable
Shootable[] shooters = new Shootable[4];
// You can store any Shootable object in your array:
shooters[0] = new MachineGun();
shooters[1] = new Revolver();
shooters[2] = new HockeyPuck();
shooters[3] = new OunceOfWhiskey();
// A Shootable object can reference any item from the array
Shootable anyShootableItem;
// The same object can to refer to a MachineGun OR a HockeyPuck
anyShootableItem = shooters[0];
anyShootableItem.beingShot();
anyShootableItem = shooters[2];
anyShootableItem.beingShot();
// You can call beingShot on any item from the array without casting
shooters[0].beingShot();
shooters[1].beingShot();
// Let's shoot each object for fun:
for (Shootable s : shooters) {
s.beingShot();
}
Here's a great related question and answer.

Object doesn't have the method beingShot. If all of the objects in array are of the same class, then your array should be of that same class. Otherwise they all should have same interface implemented or extend the same class. I can't imagine why would you want explicitly extend Object here, it doesn't add any functionality whatsoever.

You need to typecast your object references to appropriate class to call their method..
For each reference you fetch from your array, you need to check using instanceof operator, of which is the instance referred to by your object reference.. Accordingly you can typecast the reference to that class..
But Typecasting is an ugly thing.. You should avoid it as far as possible.. If you have to choose which method to invoke based on exact sub class, you should probably go with an Interface.. It is the best way you can achieve what you want here...
And I think you have got enough information about how to implement it..

You cant do it...since Java does not support extension method. (C# does)
READ THE LINK BELOW:
Java equivalent to C# extension methods

Related

Accessing instance methods that are two objects deep in Java

Say I have a class, Bobject with an instance variable and method to retrieve it:
public class Bobject {
private int bInstVar;
public Bobject() {
bInstVar = 1;
}
getBInstVar() {
return bInstVar;
}
}
If I create a class Cobject representing an object that is an array of Bobject like so:
public class Cobject {
public Bobject[] cInstVar;
public Cobject() {
cInstVar = new Bobject[2]; //arbitrary array size for simplicity of the question
for (i = 0; i <= 2; i++;) {
cInstVar[i] = new Bobject();
}
}
}
If I have a main program that creates a Cobject and attempts to access methods of the references to the Bobjects stored in each element, I find that I have to first access the Cobject instance variable, cInstVar. This means cInstVar has to be public for main() to get at it without a method if main is outside of the package or class.
My question is, is there a way around doing this:?
Cobject c = new Cobject;
c.cObject1[0].getBInstVar();
Instead, I want to have an object that is an array of another class and get to that classes instance methods easier like so:
Cobject c = new Cobject;
c.getBInstVar(); // error says 'array required, but Cobject found'
I'm still pretty new to Java (and stackExchange) so please forgive me if anything I've presented is unclear. Thanks in advance!
As a general rule of thumb class variable should be declared as private and you should use getter and settle methods....
Meaning you will need to create a getter method in 'Cobject' to get the 'Bobject' object your after.... Then another getter/setter method to access any attributes there, or a method to manipulate any data
But yes, you could hard code a method that will go into the array and return what you ask for. Probably need an index parameter tho
you can create a getter method for Bobject[] in Cobject class
and then you can do c.getCObject1()[0].getBInstVar();

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.

Keeping track of all instances of a subclass in the superclass

I have the following, stripped-down Java code:
// Class, in it's own file
import java.util.*;
public class Superclass {
protected List<Subclass> instances = new ArrayList<>();
public class Subclass extends Superclass {
private int someField;
public Subclass(int someValue) {
this.someField = someValue;
updateSuperclass();
}
private void updateSuperclass() {
super.instances.add(this);
}
}
}
// Implementation, somewhere else, everything has been imported properly
Superclass big = new Superclass();
Subclass little1 = big.new Subclass(1);
Subclass little2 = big.new Subclass(2);
Subclass little3 = big.new Subclass(3);
I want to implement a method in Superclass to do something with all the Subclasses. When a Subclass is created, it should add itself to a list in Superclass, but whenever I try to loop through that list in Superclass, it says the size is 1. The first element in the list (instances.get(0)) just spits out a String with all the proper information, but not in object form, and not separately. It's like every time I go to add to the list, it gets appended to the first (or zeroeth) element in String form.
How can I solve this so I can maintain an ArrayList of Subclasses to later loop over and run methods from? I'm definitely a beginner at Java, which doesn't help my case.
If all you need is a count then I suggest a static value that is updated in the constructor of the parent class.
private static int instanceCount = 0;
public Constructor() {
instanceCount++;
}
If you absolutely need every instance in a list so you can do something with them then I recommend you strongly re-consider your design.
You can always create a utility class that will let you maintain the list of objects to run processes on. It's more "Object Oriented" that way. You can also create one class that has all of the operations and then a simpler bean class that has only the data values.
But, if you insist, you can still use the same technique.
private static List<SuperClass> list = new LinkedList<SuperClass>;
public Constructor() {
list.add(this)
}
Each instance gets its own copy of your superclass's variables.
What you want to do is make the variable "static" by putting the static keyword before it. You probably don't even need the superclass accomplish what you're trying to do.

Prototype Pattern in Java - the clone() method

So, I've been reading on Design Patterns and the Prototype Patterns confuses me. I believe one of the points of using it is avoiding the need for using the new operator. Then I look at this example:
http://sourcemaking.com/design_patterns/prototype/java/1
First, Their idea of Prototype implements a clone() method, which is weird. Wikipedia also says I need a pure virtual method clone to be implemented by subclasses (why?). Doesn't Java already provide such a method, doing exactly what we need it to do (which is to create a copy of an object instead of instancing it from scratch)? Second, the clone method invokes the operator new! Surely the example is wrong? (In that case I should be studying Design Patterns elsewhere, heh?). Can someone tell if this correction makes it right?:
static class Tom implements Cloneable implements Xyz {
public Xyz cloan() {
return Tom.clone(); //instead of new I use clone() from Interface Cloneable
}
public String toString() {
return "ttt";
}
}
Any clarification is appreciated.
The idea of prototype pattern is having a blueprint / template from which you can spawn your instance. It's not merely to "avoid using new in Java"
If you implement prototype pattern in Java, then yes by all means override the existing clone() method from Object class, no need to create a new one. (Also need implement Clonable interface or you'll get exception)
As an example:
// Student class implements Clonable
Student rookieStudentPrototype = new Student();
rookieStudentPrototype.setStatus("Rookie");
rookieStudentPrototype.setYear(1);
// By using prototype pattern here we don't need to re-set status and
// year, only the name. Status and year already copied by clone
Student tom = rookieStudentPrototype.clone();
tom.setName("Tom");
Student sarah = rookieStudentPrototype.clone();
sarah.setName("Sarah");
A design pattern is simply a way of representing how software is written in a reproducible way. There are in fact different syntactical approaches to achieving the same thing.
So, the Prototype pattern is simply an approach that uses a master copy to implement some overriding functionality. There are several ways to do this in Java (as well, I believe in other languages). Here is one that uses the 'new' keyword, and it's based on using an interface as a contract with implementing concrete classes. Then a single method takes a concrete implementation of the interface and performs the same operation:
// software contract
interface Shape {
public void draw();
}
// concrete implementations
class Line implements Shape {
public void draw() {
System.out.println("line");
}
}
class Square implements Shape {
public void draw() {
System.out.println("square");
}
}
...
class Painting {
public static void main (String[] args) {
Shape s1 = new Line ();
Shape s2 = new Square ();
...
paint (s1);
paint (s2);
...
}
// single method executes against the software contract as a prototype
static void paint (Shape s) {
s.draw ();
}
}
You can read more at http://www.javacamp.org/designPattern/prototype.html or check out the main Design Pattern site. The information is presented there complete with references.
The example you've linked is correct and your code
return Tom.clone();
won't compile because clone() is not a static method.
Cloning is not about avoiding the use of new operator but creating a new instance that has the same state (values of its member fields) as that of the object that's being cloned. Hence, clone() is not static but an instance method so that you can create a new instance (and using new isn't a problem) that mirrors the state of the object that clone() has been invoked upon.
It's just that your example classes (like Tom) are so simple (with no state) that all that the clone() method is doing is to instantiate a new instance. If it had a bit more complex state (say an ArrayList of objects) the clone() method would have to do a deep copy of the ArrayList as well.
To elaborate with one of your example classes, assume that Tom had some instance state. Now, the clone() would also have to make sure that the copy being returned matches the state of the current one.
static class Tom implements Xyz {
private String name;
public Tom() {
this.name = "Tom"; // some state
}
public Xyz clone() {
Tom t = new Tom();
t.setName(getName()); // copy current state
return t;
}
public String toString() {
return getName();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
You can also use BeanUtils.copyProperties method to do the same which is provided by Spring framework org.springframework.beans.BeanUtils;
Prototype actually "Doesn't" save calls to new operator. It simply facilitates that a shallow copy of non-sensitive attributes are made by calling the so called clone. For example,
1) You have UserAccount which has a primary user and linked user details
2) UserAccount also has it's PK called userAccountId.
When you put all your UserAccount objects in a collection, of course, you would like the userAccountId to be different. But you still have to call new UserAccount for each links you have. Otherwise, you will end up modifying one object 100 times expecting 100 things in return. Also, if you have this UserAccount as a composition (not aggregation) depending on the attribute's sensitivity, you may have to call new on them too.
e.g if UserAccount has Person object (and if 'Person' has it's own compositions), you have to call new to ensure that their references are appropriately set.

Java run time class reflection

Say if I have a class named Car I can use the following line of code in certain situations.
Car.class
My question is there a way I can make the same type of call if a user supplies a class name at run time. Have tried something similar to the below but no joy, is there a way i can do it.
String className = "Car";
Class.forName(className ).class;
Also I need to be able to cast dynamically, if the user specifies a list of objects I need to be able to dynamically cast.
e.g. instead of Car myCar = (Car) object
I need to be able to have to the user specify the name/type of class at run time so that I need to be able to do something along the lines of ClassName myObj = (ClassName) object.
Class.forName("Car") already returns the same as Car.class.
For casting, you can then use Class.forName("Car").cast(object), which would return a Car object. Take a look at the API, mostly the java.lang.Class part of it.
Also, since you're casting # runtime, there's no type safety, and you should check whether object extends or implements Car before doing it, otherwise you'll get an exception. A question I asked ~ a year ago and the answers there may be relevant to you as well.
Though, as others already said, this smells & you could probably redesign it in a better way, also note that this type of casting will typically be pretty slow because Java needs to examine the type hierarchy (it needs to throw a ClassCastException if it can't cast to Car).
Given the nature of the question, most of the answers to this are straight from the Reflection API documentation. I would suggest you take a look at this: http://docs.oracle.com/javase/tutorial/reflect/class/index.html. If this does not help and you need help with something specific, we can look at that.
What you are looking for is a feature called Reflection in the Java programming language.
It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members and display them.
A Simple Example from http://java.sun.com
import java.lang.reflect.*;
public class DumpMethods {
public static void main(String args[])
{
try {
Class c = Class.forName(args[0]);
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
System.out.println(m[i].toString());
}
catch (Throwable e) {
System.err.println(e);
}
}
}
For an invocation of:
java DumpMethods java.util.Stack
the output is:
public java.lang.Object java.util.Stack.push(
java.lang.Object)
public synchronized
java.lang.Object java.util.Stack.pop()
public synchronized
java.lang.Object java.util.Stack.peek()
public boolean java.util.Stack.empty()
public synchronized
int java.util.Stack.search(java.lang.Object)
Here is an example of creating objects at runtime:
import java.lang.reflect.*;
public class constructor2 {
public constructor2()
{
}
public constructor2(int a, int b)
{
System.out.println(
"a = " + a + " b = " + b);
}
public static void main(String args[])
{
try {
Class cls = Class.forName("constructor2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Constructor ct
= cls.getConstructor(partypes);
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = ct.newInstance(arglist);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
You can read more about it here and here - for indepth view
Also look here:
What is reflection and why is it useful?
You want to interact with myObj, so rather than going through these gymnastics, think about adding an interface that models the interactions you want to have with the objects, then use that interface in the code. The classes supplied by the user can then be validated to implement the necessary interface and errors raised appropriately.
The expression Car.class returns the java.lang.Class object for class Car.
A statement Class.forName("Car") will also return the java.lang.Class object for class Car (assuming that class Car is in the default package). Note: No need to append .class; that would give you the Class object of class Class itself, which is not what you want.
Class Class has methods to check if an object is an instance of the class that the Class instance represents (hope this is not too confusing...). Since you don't know the name of class Car at compile time, you're not going to have any kind of compile time type safety.
Lookup the API documentation of java.lang.Class.

Categories

Resources