Array of objects of different types - java

I'm programming a game as Java applet, and I have two different classes with similar variables - Pavement and Way.
I would like to create an Array that will contain objects from both classes. I have to change for example x and y of all these objects so I would like to create an Array. Is this possible to do?
I have tried ArrayList<Object> obj = new ArrayList<Object>(); but if I obj.add(0, theWay); I can't find a way to read variables.
I also tried System.out.print(obj.get(0)); and got rpg.way#2c61bbb7.

In short, you would like to call a method (like setX()) on a Way instance, or on a Pavement instance, without knowing if the object is a Way or a Pavement.
This is exactly the problem that polymorphism solves. Define an interface Locatable, and make your two classes implement this interface. Then create a List<Locatable>, and you'll be able to add Ways and Pavements inside it:
public interface Locatable {
public void setX(int x);
public void setY(int y);
public int getX();
public int getY();
}
public class Way implements Locatable {
...
}
public class Pavement implements Locatable {
...
}
List<Locatable> locatables = new ArrayList<Locatable>();
list.add(new Way());
list.add(new Pavement());
for (Locatable locatable: locatables) {
locatable.setX(22);
locatable.setY(43);
}
for (Locatable locatable: locatables) {
System.out.println("the locatable is an instance of " + locatable.getClass());
System.out.println("its location is " + locatable.getX() + ", " + locatable.getY());
}

You can use ArrayList<Object> and you check the type of the objects.
For instance:
ArrayList<Object> L = new ArrayList<Object>();
//..add objects
for (Object o : L){
if(o.getClass() == Class1.class){
Class1 obj1 = (Class1) o;
//...
}else if(o.getClass() == Class2.class){
Class2 obj2 = (Class2) o;
//...
}else{
//...
}
}
You can also use instanceof to check the type.

You mention the classes are different but similar? If the classes are similar enough that you want to try calling the same methods on the classes, you may want to consider generalizing the classes using an abstract class: This is much better practice than the "instance of" and caste solution. You could also use an interface, but the abstract class allows you to actually implement changeX() and changeY() if they work the same way. For example, if you want to call changeX(int x) or changeY(int y) on either of the objects regardless of whether they are Way or Pavement objects, you probably want to do something like this:
public abstract class Changeable
{
public void changeX(int x) {
this.x = x;
}
public void changeY(int y) {
this.y = y;
}
protected int x;
protected int y;
}
public Class Pavement extends Changeable{ ... }
public Class Way extends Changeable{ ... }
At which point you can create an array of the interface and insert objects inside like so:
List<Changeable> paths = new ArrayList<Changeable>();
paths.add(new Way());
paths.add(new Pavement());
Changeable path = paths.get(0);
path.changeX(5);
path.changeY(7);

Related

Efficient way to keep referencing a class in multiple linked java classes?

suppose in Eclipse I have three packages with the following classes in each:
Packages: Classes
Head: head.java
Body: arms.java
Legs: feet.java
I want to define class info in brain.java and pass it through methods to the other classes (arms.java and feet.java) and update the contents of info.
class info {
// some vars such as bools,ints,strings
}
For example, have updateArms be a method defined in arms.java. I want to do the following in brain.java:
arms.updateArms( info );
I am having trouble finding how to first define a class that behaves this way, and secondly how to pass it as a parameter to another linked class.
First, you should learn about Java naming convention.
For example, package should be head, and the class should be Head.
Go back to your design: In OOP, we see the program as interactions between object instances.
In your example, it may look like:
class Arm {
void moveUp(SomeInfo info) {
...
}
}
class Brain {
private Arm leftArm;
private Arm rightArm;
void reachForward() {
rightArm.moveUp(...);
}
void connectLeftArm(Arm arm) {
this.leftArm = arm;
}
//....
}
class Body {
Brain brain;
Arm leftArm;
Arm rightArm;
public Body() {
this.brain = new Brain();
this.leftArm = new Arm();
this.rightArm = new Arm();
this.brain.connectLeftArm(this.leftArm);
this.brain.connectRightArm(this.rightArm);
}
}
I wish this demonstrate the difference of way of thinking.
If you start get used to the way OOP see things, then you can take next step in refining your design (e.g. by different design pattern)
You can achieve this using Inheritance.
Inheritance can be defined as the process where one class acquires the properties (methods and fields) of another. With the use of inheritance the information is made manageable in a hierarchical order. The class which inherits the properties of other is known as subclass (derived class, child class) and the class whose properties are inherited is known as superclass (base class, parent class).
Sample Code helps you how to use the methods and properties of other classes.
class Calculation {
int z;
public void addition(int x, int y) {
z = x + y;
System.out.println("The sum of the given numbers:"+z);
}
public void Subtraction(int x, int y) {
z = x - y;
System.out.println("The difference between the given numbers:"+z);
}
}
public class My_Calculation extends Calculation {
public void multiplication(int x, int y) {
z = x * y;
System.out.println("The product of the given numbers:"+z);
}
public static void main(String args[]) {
int a = 20, b = 10;
My_Calculation demo = new My_Calculation();
demo.addition(a, b);
demo.Subtraction(a, b);
demo.multiplication(a, b);
}
}

How would I access an int variable from one class to another? (Java)

For example:
In Class One
int killcount = 0;
In Class Two
killcount = 5;
All I want to do I get the variable from one class to another class. How would I do that?
Before trying to work with Bukkit I'd recommend you to get some Java experience first. That's not meant as an insult, but it can get quite confusing if you do it the other way round. Anyways, if you still want to know the answer to your question:
You'll have to create a getter & setter for your "killcount" variable.
class Xyz {
private int killcount;
public void setKillcount(int killcount) {
this.killcount = killcount;
}
public int getKillcount() {
return this.killcount;
}
}
Of course this is a simplified version without checks, but if you want to access the variable from a different class you can create an instance and use the methods to modify it.
public void someMethod() {
Xyz instance = new Xyz();
instance.setKillcount(instance.getKillcount() + 1);
//this would increase the current killcount by one.
}
Keep in mind that you'll have to use the same instance of the class if you want to keep your values, as creating a new one will reset them to default. Therefore, you might want to define it as a private variable too.
Consider the examples
public class Test {
public int x = 0;
}
This variable x can be accessed in another class like
public class Test2 {
public void method() {
int y = new Test().x;
// Test.x (if the variable is declared static)
}
}
Ideally, the instance variables are made private and getter methods are exposed to access them
public class Test {
private int x = "test";
public int getX() {
return x;
}
public void setX(int y) {
x = y;
}
}

inherit all getter/setter methods of a java obj

I have a class A with a number of setter/getter methods, and want to implement a class B which "extends A" and provides other functionality.
I cannot modify class A, and it doesn't have a clone or constructor method that that takes a class A obj as a parameter. So basically I implement class B such that
it has a constructor that takes a class A obj as a parameter and keeps a copy of this obj
when we call setter/getter methods on B, it delegates to the class A obj
other functionality...
Class A has many setter/getter methods and I feel this implementation is not clean but not sure how to fix this. Usually I can make B extend A, but in this case I have to be able to take a class A obj as a parameter for the constructor.
I'm sorry if the question is not clear enough, please let me know if you need more clarifications. Thanks.
Example:
public class A {
private int x;
public void setX(int x) { this.x = x; }
public int getX() { return this.x; }
}
public class B {
private A a;
public B(A a) { this.a = a; }
public void setX(int x) { a.setX(x); }
public int getX() { return a.getX(); }
public void foo() { ... };
public void bar() { ... };
}
Basically A has a lots of properties X/Y/Z... and has many setters/getters. If I do this then B have many dummy setters/getters which simply delegate to the same call on a. Is there a cleaner way to implement this?
I think you're trying to extend an object of class A to add functionality to it and this is creating this dilemma. You can't copy A easily with a copy constructor and so you're trying to use composition rather than inheritance, and then that's not working.
Three options:
Do what you're doing - wrap the object of type A as something owned by B and delegate - it works and it's not too bad
Subclass A with B and then use some sort of reflection based copy routine to copy all properties from the object of type A into the new object of type B - e.g. http://commons.apache.org/proper/commons-beanutils/ copyProperties function
Create a copy constructor in class B that does what you want
Example
public class A {
private int x;
public void setX(int x) { this.x = x; }
public int getX() { return this.x; }
}
public class B {
public B(A a) {
// copy all A properties from the object that we're going to extend
this.setX(a.getX());
}
.. other stuff
}
The problem you're describing is one of extending an object. Extending a class is straightforward - just subclass it, and you have the base implementation plus your new stuff. To extend an object with the above code:
A someA = new A();
// a is initialised as an A
B aWithExtraProperties = new B(someA);
// now you have a B which has the same values as the original A plus
// b's properties
// and as B subclasses A, you can use it in place of the original A
I've tried changing an object's type at runtime like this before and it doesn't feel nice. It may be better to consider why you're doing this at all and whether there are alternatives.
If class B extends class A, it will automatically inherit all its non-private non-static methods. In your code, the getter/setters in class A are declared public, so class B will inherit them.
However, for this to work, you will need to rewrite class B's signature as follows, abd remove pretty much all code you wrote in B's body :
public class B extends A {
// here, put any functionalities that B provides in addition to those inherited from A
}
This way, you can access all the getter/setters through any reference of type A or B, like this :
public static void main(String... args) {
A a = new A();
a.setName("Bob");
System.out.println(a.getName());
B b = new B();
b.setName("Joe");
System.out.println(b.getName());
// And even this, thanks to polymorphism :
A ab = new B();
ab.setName("Mike");
System.out.println(ab.getName());
}

use variable with "new" when creating object

I am designing a virtual aquarium. I have a class: Fish which I inherit to create classes of different species. The user can select the species in a combo box and click a button to put the fish in the tank. I use the following code to create the fish:
switch(s){
case "Keegan" :
stock.add(new Keegan(this, x,y));
break;
case "GoldenBarb" :
stock.add(new GoldenBarb(this, x,y));
"stock" is a LinkedList and "s" is the String selected in the Jcombobox. As it stands I will have to create a long switch when I add a bunch of different species. I would like the code to look like:
stock.add(new s(this,x,y));
and dispense with the switch such that all I have to do is create the class and add its name to the combo box and have it work. Is there a way to do so? Any help is appreciated.
You want to use a bunch of factory objects, stored in a Map under the string keys that you use in the switch.
These are the classes for the various fish you should already have.
abstract class FishBase {}
class Keegan extends FishBase {
Keegan(Object _this, int x, int y) {
// ...
}
}
class GoldenBarb extends FishBase {
GoldenBarb(Object _this, int x, int y) {
// ...
}
}
An interface for all the fish factories. A fish factory represents a way to create some type of fish. You didn't mention what the constructor signature is so I just picked some types.
interface IFishFactory {
FishBase newFish(Object _this, int x, int y);
}
Set up one factory for every fish type. These obviously don't need to be anonymous classes, I'm using them to cut down on clutter.
Map<String, IFishFactory> fishFactories = new HashMap<>();
fishFactories.put("Keegan", new IFishFactory() {
public FishBase newFish(Object _this, int x, int y) {
return new Keegan(_this, x, y);
}
});
fishFactories.put("GoldenBarb", new IFishFactory() {
public FishBase newFish(Object _this, int x, int y) {
return new GoldenBarb(_this, x, y);
}
});
Then just pick the factory from the Map using the string you already have. You might want to check whether a factory for the given name exists.
stock.add(fishFactories.get(s).newFish(this, x, y));
Now, if all your fish classes have the exact same constructor signature, you can create a single factory class that can handle all of them using reflection, and get rid of some boilerplate.
class ReflectionFishFactory implements IFishFactory {
Constructor<? extends FishBase> fishCtor;
public ReflectionFishFactory(Class<? extends FishBase> fishClass)
throws NoSuchMethodException {
// Find the constructor with the parameters (Object, int, int)
fishCtor = fishClass.getConstructor(Object.class,
Integer.TYPE,
Integer.TYPE);
}
#Override
public FishBase newFish(Object _this, int x, int y) {
try {
return fishCtor.newInstance(_this, x, y);
} catch (InstantiationException
| InvocationTargetException
| IllegalAccessException e) {
// this is terrible error handling
throw new RuntimeException(e);
}
}
}
Then register it for every applicable subclass.
for (Class<? extends FishBase> fishClass :
Arrays.asList(Keegan.class,GoldenBarb.class)) {
fishFactories.put(fishClass.getSimpleName(),
new ReflectionFishFactory(fishClass));
}
I think reflection might be what you are looking for. This allows you to avoid the switch statement, which is what you are asking.
Reflection (among other things) allows you to run methods with just strings. So in Java, where you would normally call a method like this:
new Foo().hello();
With Reflection, you can use a string to call the method, like this:
Class<?> clazz = Class.forName("Foo");
clazz.getMethod("hello").invoke(clazz.newInstance());
Java Constructor Reflection example.
Regarding the Factory pattern (referring now to other answers), as I understand it, that is just encapsulating the switch statement (or whatever method you choose to use). The Factory pattern itself is not a means of avoiding the switch statement. The Factory Pattern is a good thing, but not what you were asking. (You will probably want to use the factory pattern in any case).
Let's go step by step to see how far you want to go.
First, you can abstract out the creation of fish in a FishFactory, so that the original place you do the switch statement can simply changed to
stock.add(fishFactory.createFish(s, x, y));
Then the switch case goes to the factory:
public class SimpleFishFactory {
#Override
public Fish createFish(String fishType, int x, int y) {
switch(s){
case "Keegan" :
return new Keegan(this, x,y);
break;
case "GoldenBarb" :
return new GoldenBarb(this, x,y);
//....
}
}
}
(I assume all your fish is having same interface/base class as Fish)
If you want to make the creation look more elegant, there are two common ways to choose from:
Reflection
Idea is simple. First setup a lookup table of string vs fish class (or constructor), and each createFish() is creating new instance of fish by reflection
public class ReflectionFishFactory {
private Map<String, Class<? extends Fish>> fishClasses = new HashMap<...>();
public ReflectionFishFactory() {
//set up fishClasses with name vs corresponding classes.
// you may read it from file, or hard coded or whatever
fishClasses.put("Keegan", Keegan.class);
fishClasses.put("GoldenBarb", GoldenBarb.class);
}
#Override
public Fish createFish(String fishType, int x, int y) {
Class<?> fishClass = fishClasses.get(fishType);
// use reflection to create new instance of fish by
// by using fishClass
}
}
Prototype Pattern
For some reason, you may not want to use reflection (maybe due to slowness of reflection, or different fishes have very different way to create), you may look into Prototype Pattern of GoF.
public class PrototypeFishFactory {
private Map<String, Fish> fishes = new HashMap<...>();
public ReflectionFishFactory() {
//set up fishClasses with name vs corresponding classes.
// you may read it from file, or hard coded or whatever
fishClasses.put("Keegan", new Keegan(....) );
fishClasses.put("GoldenBarb", new GoldenBarb(....) );
}
#Override
public Fish createFish(String fishType, int x, int y) {
return fishes.get(fishType).cloneNewInstance(x, y);
}
}
A combination of enums and factory strategies could be used for a simple, type-safe, way of creating object instances from Strings and for providing a set (or array) of Strings.
Take the follwoing eample -
import java.util.HashMap;
import java.util.Map;
public enum FishType {
BLUE_FISH(BlueFish.class, new FactoryStrategy<BlueFish>(){
public BlueFish createFish(int x, int y) {
return new BlueFish(x, y);
}}),
RED_FISH(RedFish.class, new FactoryStrategy<RedFish>(){
public RedFish createFish(int x, int y) {
//an example of the increased flexibility of the factory pattern - different types can have different constructors, etc.
RedFish fish = new RedFish();
fish.setX(x);
fish.setY(y);
fish.init();
return fish;
}});
private static final Map<Class<? extends Fish>, FactoryStrategy> FACTORY_STRATEGY_MAP = new HashMap<Class<? extends Fish>, FactoryStrategy>();
private static final String[] NAMES;
private FactoryStrategy factoryStrategy;
private Class<? extends Fish> fishClass;
static {
FishType[] types = FishType.values();
int numberOfTypes = types.length;
NAMES = new String[numberOfTypes];
for (int i = 0; i < numberOfTypes; i++) {
FishType type = types[i];
FACTORY_STRATEGY_MAP.put(type.fishClass, type.factoryStrategy);
NAMES[i] = type.name();
}
}
<F extends Fish> FishType(Class<F> fishClass, FactoryStrategy<F> factoryStrategy) {
this.fishClass = fishClass;
this.factoryStrategy = factoryStrategy;
}
public Fish create(int x, int y) {
return factoryStrategy.createFish(x, y);
}
public Class<? extends Fish> getFishClass() {
return fishClass;
}
public interface FactoryStrategy<F extends Fish> {
F createFish(int x, int y);
}
#SuppressWarnings("unchecked")
public static <F extends Fish> FactoryStrategy<F> getFactory(Class<F> fishClass) {
return FACTORY_STRATEGY_MAP.get(fishClass);
}
public static String[] names() {
return NAMES;
}
}
This enum could then be used in the following manner -
Fish fish = FishType.valueOf("BLUE_FISH").create(0, 0);
or
Fish fish = FishType.RED_FISH.create(0, 0);
or, if you need to know the type of the created fish, you can use this call -
BlueFish fish = FishType.getFactory(BlueFish.class).createFish(0, 0);
To populate the items in a menu or obtain all fish types for any other reason, you can use the names() method -
String[] names = FishType.names();
To add new types, the only code that needs to be edited is to add a new enum declaration such as
GREEN_FISH(GreenFish.class, new FactoryStrategy<GreenFish>(){
public GreenFish createFish(int x, int y) {
return new GreenFish(x, y);
}}),
It may seem like a lot of code, but it's already been written, it provides a clean API to call from other code, it provides pretty good type-safety, allows the fish implementations the flexibility to have whatever constructors or builders that they want, it should be fast performing, and it doesn't require you to pass around arbitrary string values.
If you are just really into keeping it concise, you could also use a template method in the enums -
public enum FishType {
BLUE_FISH(){
public BlueFish create(int x, int y) {
return new BlueFish(x, y);
}
},
RED_FISH(){
public RedFish create(int x, int y) {
return new RedFish();
}
};
public abstract <F extends Fish> F create(int x, int y);
}
With this, you still get a lot of the same functionality such as
Fish fish = FishType.valueOf("BLUE_FISH").create(0, 0);
and
Fish fish = FishType.RED_FISH.create(0, 0);
and even
RedFish fish = FishType.RED_FISH.create(0, 0);
Study the Factory Design Pattern. That is essentially what you are doing here, but will be a little bit cleaner if you use it explicitly.
It is not always just a giant switch statement. For instance, you may have a table of dynamically loaded assemblies and/or types, each of which have a function called "GetTypeName" and another function called "CreateInstance". You would pass a string to a factory object, which would look in the table for that typename and return the result of the CreateInstance function on that factory object.
No, this isn't reflection, people were doing this long before Java came along. This is how COM works for example.
Reflection seems to be the best solution for this issue and I am glad to have this technique in my toolbox. Here is the code that worked:
public void addFish(String s, int qt){
try{
Class<?> theClass = Class.forName("ftank." + s);
Class[] ctorArgs = {ftank.FishTank.class};
Constructor ctor = theClass.getDeclaredConstructor(ctorArgs);
for(int i=0;i<qt;i++){stock.add((Fish)ctor.newInstance(this));}
} catch (ClassNotFoundException e) {...
I had to include the package name as part of the class string. I also had to make the constructors public. I was unable to implement this solution with int arguments in the constructors but I managed to find a way around using them which was cleaner anyways. The only problem now is that I must update the array of Strings used in the JComboBox everytime
I add a new species of Fish. If anyone knows a way of having java generate a list of the names of all the classes in a package which inherit from a given base class that would be helpful. Your suggestions so far were very helpful and I am greatful.

generics calling constructor

I am trying to do something I would not normally do, it is a bit odd, but I'd like to make it work. Essentially I have a factory that has to create objects by calling the constructor with different types of data (A and B take different types in the code below). I seem to have gotten my self stuck going down the generics route (I do need the code to be as compile time typesafe as possible). I am not opposed to writing the code differently (I'd like to keep the idea of the factory if possible, and I do not want to have to add in casts - so the "data" parameter cannot be an "Object").
Any thoughts on how to fix the code with generics or an alternative way of doing it that meets my requirements?
(Technically this is homework, but I am the instructor trying out something new... so it isn't really homework :-)
public class Main2
{
public static void main(String[] args)
{
X<?> x;
x = XFactory.makeX(0, "Hello");
x.foo();
x = XFactory.makeX(1, Integer.valueOf(42));
x.foo();
}
}
class XFactory
{
public static <T> X<T> makeX(final int i,
final T data)
{
final X<T> x;
if(i == 0)
{
// compiler error: cannot find symbol constructor A(T)
x = new A(data);
}
else
{
// compiler error: cannot find symbol constructor B(T)
x = new B(data);
}
return (x);
}
}
interface X<T>
{
void foo();
}
class A
implements X<String>
{
A(final String s)
{
}
public void foo()
{
System.out.println("A.foo");
}
}
class B
implements X<Integer>
{
B(final Integer i)
{
}
public void foo()
{
System.out.println("B.foo");
}
}
I don't see a way to make it work. I don't really think it should work either. When calling your makeX() function the calling code needs to know what integer parameter corresponds to what type of data to pass in. IOW, your abstraction is very leaky in the first place, and what you're really implementing is a rudimentary form of polymorphism, which you might as well use method overloading for, i.e.:
X makeX(String data) {
return new A(data);
}
X makeX(Integer data) {
return new B(data);
}
Of course it's a toy problem and all that. One way to make it work would be to make the client aware of implementation classes and add a Class<T> argument that you instantiate through reflection. But I suppose that would be kind of defeating the purpose.
I don't think what you're trying to do is possible without casting.
With casting, you have two options
if(i == 0)
{
x = new A((Integer)data);
}
else
{
x = new B((String)data);
}
}
or
class A
implements X<String>
{
A(final Object s)
{
}
}
...
class B
implements X<Integer>
{
B(final Object i)
{
}
}
Probably the closest thing you could get whilst retaining static type safety and having lazy construction is:
public static void main(String[] args) {
X<?> x;
x = aFactory("Hello").makeX();
x.foo();
x = bFactory(42).makeX();
x.foo();
}
private static XFactory aFactory(final String value) {
return new XFactory() { public X<?> makeX() {
return new A(value);
}};
}
public static XFactory bFactory(final Integer value) {
return new XFactory() { public X<?> makeX() {
return new B(value);
}};
}
interface XFactory() {
X<?> makeX();
}
So we create an instance of an abstract factory that creates the appropriate instance with the appropriate argument. As a factory, the product is only constructed on demand.
Clearly something had to give. What would you expect XFactory.makeX(1, "Hello") to do?
This is not possible without casting. As I have said elsewhere - generics don't remove the need for casting, but they mean that you can do all the casting in one place.
In the setup you describe, the factory method is exactly where all the under-the-hood work takes place. It's the spot where your code tells the compiler "I know you don't know what these types are, but I do, so relax.
It's entirely legit for your factory method to know that if i==1, then the data must be be of type Integer, and to check/enforce this with casting.

Categories