I have the following HashMap:
HashMap<Integer, Object> ItemsData = new HashMap<Integer, Object>();
In the HashMap, I have objects of various classes, such as
ClassOne
ClassTwo
ClassThree
Each class has its own methods, attributes etc.
How do I refer to proper method, depending on the instance of the class?
For example:
ItemsData.get(5).bark() -> because item 5 is instance of class 1 which has method bark
ItemsData.get(2).jump() -> because item 2 is instance of class 2 which has method jump
ItemsData.get(6).fire() -> because item 6 is instance of class 3 which has method fire
Generally having such an untyped map in the first place is a code smell. You didn't explain enough of the underlying problem you're trying to solve to give you good advice on a nicer solution; merely to point out that this solution probably is severely suboptimal.
If you insist on using it, you can use instanceof to check if a value is of a certain type, and use a cast operator to treat it as a certain type:
Map<Integer, Object> badIdea = new ....;
...
Object secondValue = badIdea.get(1);
if (secondValue instanceof Dog) {
Dog dog = (Dog) secondValue;
dog.bark();
}
Create an interface, eg:
interface Actor {
void act();
}
And keep a collection of those:
Map<Integer, Actor> ItemsData = new HashMap<>();
Have your classes implement Actor, either directly:
public ClassOne implements Actor {
public void act() {
// make a barking noise
}
// other fields and methods
}
or indirectly:
public ClassOne implements Actor {
public void act() {
bark();
}
public void bark() {
// make a barking noise
}
// other fields and methods
}
Then invoke Actor's method instead of the original specific method:
itemsData.get(5).act();
You can also invoke all conveniently:
itemsData.forEach(Actor::act);
For a full discussion of this idea, read Liskov substitution principle.
Related
The whole time I thought, if I am using a List like List<Thing> things = new ArrayList<>() all items in this list are of Type Thing. Yesterday i was taught the other way.
I've created the following stuff and wonder why it is like it is.
An Interface Thing
public interface Thing {
String getType();
String getName();
}
A class ObjectA
public class ObjectA implements Thing {
private static final String TYPE = "Object A";
private String name;
public ObjectA(String name) {
this.name = name;
}
#Override
public String toString() {
final StringBuffer sb = new StringBuffer("ObjectA{");
sb.append("name='").append(name).append('\'');
sb.append('}');
return sb.toString();
}
#Override
public String getType() {
return TYPE;
}
#Override
public String getName() {
return name;
}
// equals and hashCode + getter and setter
}
A class ObjectB
public class ObjectB implements Thing {
private static final String TYPE = "Object B";
private String name;
private int value1;
private String value2;
private boolean value3;
public ObjectB(String name, int value1, String value2, boolean value3) {
this.name = name;
this.value1 = value1;
this.value2 = value2;
this.value3 = value3;
}
#Override
public String getType() {
return TYPE;
}
#Override
public String getName() {
return name;
}
#Override
public String toString() {
final StringBuffer sb = new StringBuffer("ObjectB{");
sb.append("name='").append(name).append('\'');
sb.append(", value1=").append(value1);
sb.append(", value2='").append(value2).append('\'');
sb.append(", value3=").append(value3);
sb.append('}');
return sb.toString();
}
// equals and hashCode + getter and setter
}
The main method
public static void main(String[] args) {
final List<Thing> things = new ArrayList<>();
final ObjectA objA = new ObjectA("Thing 1");
final ObjectB objB = new ObjectB("Thing 2", 123, "extra", true);
things.add(objA);
things.add(objB);
// The List doesn't contain Thing entities, it contains ObjectA and ObjectB entities
System.out.println(things);
for(final Thing thing : things) {
if (thing instanceof ObjectA) {
System.out.println("Found Object A: " + thing);
final ObjectA object = (ObjectA) thing;
}
if (thing instanceof ObjectB) {
System.out.println("Found Object B: " + thing);
}
}
}
The output of this method is:
[ObjectA{name='Thing 1'}, ObjectB{name='Thing 2', value1=123, value2='extra', value3=true}]
So i assume i've ObjectA entities and ObjectB entities in my List<Thing>.
Question: Can someone provide a link (or some keywords which can be used for searching), which explain this behavior, or can explain it to me?
additional Question: I've started to filter this List<Thing> with instanceof but i have read instanceof and casting are bad practice (e.g. no good model design). Is the are "good" way to filter this List for all Types of ObjectA to perform only on these objects some operations?
You should avoid instanceof check in your additional question example. When you work with List items, it should be sufficient to have interface methods available. If you need to do something with only ObjectA or ObjectB, I suggest to use another List with only ObjectA or ObjectB. For example you can define different methods to do Thing specific job and ObjectB specific job:
public void processThings(List<Thing> things) {
for(final Thing thing : things) {
// we work only with methods that provided by interface Thing
System.out.println(thing.getType());
System.out.println(thing.getName());
}
}
public void processObjectsB(List<ObjectB> objectsB) {
// here we do some specific things with only B objects,
// assuming class ObjectB has an additional method doSomeSpecificB()
for(final ObjectB objectB : objectsB) {
objectB.doSomeSpecificB();
}
}
I have a garden that contains potatoes, carrots and broccoli. I have a very strict rule - I won't plant anything in the garden that I can't eat. So no poison ivy here!
So this is a Garden<Edible> - everything I plant in the garden has to be edible.
Now class Potato implements Edible means that every potato is edible. But it also means that I can plant a potato in my garden. Likewise, class Carrot implements Edible - all carrots are edible, and I'm allowed to plant carrots.
It's a dark night, and I'm hungry. I go out to my garden and put my hand on something in the garden. I can't see what it is, but I know that everything in my garden is edible. So I pull it out of the garden, and take it inside to cook and eat. It doesn't matter what I've grabbed - I know it will be something I can eat.
Because this is a Garden<Edible>. It may or may not contain Potato objects. It may or may not contain Broccoli objects. It does not contain PoisonIvy objects.
Now, translate that all to your example. You have class ObjectA implements Thing - which means that every ObjectA is a Thing. You have class ObjectB implements Thing - which means that every ObjectB is a Thing. And you have a List<Thing> - a List that can contain ObjectA objects, ObjectB objects, and any other object of any class that implements Thing. What you can't put in it is an object of any class that doesn't implement Thing.
Can someone provide a link (or some keywords which can be used for searching), which explain this behavior, or can explain it to me?
This behaviour is called "polymorphism". Basically, since ObjectA and ObjectB implements Thing, instances of ObjectA and ObjectB can be used like a Thing object. In your code, you added them to a list that can contain Thing objects.
Note how even if those objects are now of (compile time) type Thing, at runtime they still know what they are. When you call toString on them, the respective overridden toString methods in ObjectA and ObjectB will be called. It is as if the Thing "morphs" into ObjectA or ObjectB.
Is the are "good" way to filter this List for all Types of ObjectA to perform only on these objects some operations?
The reason why people say this is bad practice is because if you want to do different things depending whether the object is ObjectA or ObjectB, why did you make them implement Thing and make a list of Thing to store them? You could have just used a List<Object>. The real advantage of using List<Thing> is that you avoid knowing what actual objects are in there when you are working with the list. All you know is that the things inside the list implement Thing and you can call methods declared in Thing.
So if you need to filter the list to separate the two types, you could have just created two lists to store them in the first place. One for ObjectA and one for ObjectB. Obviously, this is not always possible, especially if the list comes from somewhere else (like a external library). In that case, your current code is fine.
things is a List<Thing>. That means that at compile time, Java will ensure that any object that you write to things is a Thing. As ObjectA and ObjectB both implement Thing the actual implementation of any member of things can be ObjectA or ObjectB. This is by design and that feature is called polymorphism: object of different classes share a common interface and can be accessed thrrough that interface independently of their actual type. For example you could use:
for(final Thing thing : things) {
System.stdout.println("Found a " + thing.getType() + " named " + thing.getName());
}
Using instanceof and casting is not necessarily bad practice and can have correct use case. But it is often a hint that the hierachy of classes and interfaces has not been properly designed. Ideally, if you have to process a Thing, you should not wonder about its actual class: you have a Thing, and using Thing methods should be enough.
In that sense, instanceof is at the same level as reflection is: it is a low level tool that allows to see what is hidden under the hood. And any time you use it, you should ask you whether polymorphism could not be enough.
I need to store lots of objects that belong to different classes:
ClassA {...}
ClassA1 extends ClassA {...}
ClassA2 extends ClassA {...}
ClassA2a extends ClassA2 {...}
ClassB {...}
Now I need to find a way to store all these objects in a way that allows me to efficiently get all objects that belong to a particular class and its inherited child classes. For example, this imaginary code
getObjects(ClassA2)
would return a list of all stored objects that belong to ClassA2 or ClassA2a.
I believe a tree collection of some sort would be suitable, but I can't think of any way to implement it. Any ideas?
(Background: I am creating a simple java game, in which there's number of sprites that I need to manage, while some of those sprites share similar properties. When I check for events like collisions, I need to get all objects that extend EnemySprite and compare their coordinates with the player's sprite.)
There are several ways how to approach this. One would be, e.g., to generate strings like ParentClass1:ChildClass2:ChildClass1: for every object and use them as a key to a TreeMap or Trie which you would then traverse.
Here is a simpler solution, though. The following class contains a map from class to all objects implementing it. The only trick is adding an object to all buckets where it belongs:
public class HierarchyMap {
private final Map<Class<?>, List<Object>> map = new HashMap<>();
public void add(Object o) {
Class<?> clazz = o.getClass();
while (clazz != Object.class) {
List<Object> list = map.computeIfAbsent(clazz, c -> new ArrayList<>());
list.add(o);
clazz = clazz.getSuperclass();
}
}
public List<Object> getByClass(Class<?> clazz) {
return map.get(clazz);
}
}
Usage:
public class A { public String toString() { return "A"; } }
public class B extends A{ public String toString() { return "B"; } }
public class C extends B { public String toString() { return "C"; } }
// ...
HierarchyMap hierarchyMap = new HierarchyMap();
hierarchyMap.add(new A());
hierarchyMap.add(new B());
hierarchyMap.add(new C());
System.out.println(hierarchyMap.getByClass(B.class));
// prints [B, C]
Mifeet seems to have literally answered your question, but I suspect you shouldn't be trying to do what you're proposing to do. Why not just have a master list of all objects that might collide, then filter it as needed using instanceof?
This is conceptually a lot easier than what you're proposing to do, and the efficiency impact probably isn't that big. (In general, you will probably hear or have heard the mantra: Don't try to optimize too early.)
To be honest, I'm not sure you realize that filtering for EnemySprite will get you all object instances of its subclasses as well.
public class CollisionChecker(){
private List colliders;
public CollisionChecker(){
colliders = new ArrayList<Object>();
}
public void addCollider(Object o){
colliders.add(o);
}
public List<EnemySprite> getEnemySprites(){
List<EnemySprite> enemies = new ArrayList<EnemySprite>();
for (Object o : colliders)
if (o instanceof EnemySprite)
enemies.add((EnemySprite)o);
return enemies;
}
}
If you're storing the objects in a List<Object>, call Class#isInstance() on each element, adding them to another List if isInstance() returns true.
List<Object> objects = new ArrayList<>();
public <T> List<T> getObjects(Class<T> desiredClass) {
List<T> desiredObjects = new ArrayList<>();
for (Object o : objects)
if (desiredClass.isInstance(o))
desiredObjects.add((T)o);
return desiredObjects;
}
getObjects(EnemySprite.class); // call it like this
If you just want collision detection, then I would add them to a static collection in the ancestor class. This would be the most efficient solution.
If you want to all descendants for a class you should check out the reflection APIs. Yes, they're said to be slow, but I have doubts that it matters enough for things that aren't computed for every frame. And for things that you need in every frame tree traversal would inefficient anyway. (#Miffet's suggestion of string comparison would probably be even slower than regular reflection.)
Let's say I'm building an immutable Yahtzee scorecard class:
public final class Scorecard {
private Map<Category, Integer> scorecard = new HashMap<Category, Integer>();
public Scorecard() {
// Instantiates a new empty scorecard
}
private Scorecard(Map<Category, Integer> scorecard) {
this.scorecard = scorecard;
}
public Scorecard withScore(Category category, int[] roll) {
newScorecard = new HashMap<Category, Integer>(scorecard); // Pretend that this is a deep-copy
newScorecard.put(category, calculateScoreFromRoll(roll));
return new Scorecard(newScorecard);
}
public int getScore(Category category) {
return scorecard.get(category);
}
}
Basically I don't want to expose the internals of the class. If I didn't have a private constructor then I would need to use a public constructor with a Map argument just like the private one (and I could essentialy lose the withScore() method too) in order to allow scoring. But is this a valid way of doing factory methods?
A very common, and good pattern is to have all private constructors and public static factory methods:
public class MyClass {
private MyClass() {}
public static MyClass fromA(A foo) {
MyClass o = new MyClass();
o.field = bar; // etc
return o;
}
public static MyClass fromB(B foo) {
MyClass o = new MyClass();
o.field = bar; // etc
return o;
}
}
Note: This allows different factory methods with the same parameter types, which constructors do not allow.
Factory methods are intended to allow you to get an object without specifying the exact type.
For example, from Effective Java, 2nd edition:
The class java.util.EnumSet (Item 32), introduced in release 1.5, has no public constructors, only static factories. They return one of two implementations, depending on the size of the underlying enum type: if it has sixty-four or fewer elements, as most enum types do, the static factories return a RegularEnumSet instance, which is backed by a single long; if the enum type has sixty-five or more elements, the factories return a JumboEnumSet instance, backed by a long array.
The existence of these two implementation classes is invisible to clients. If RegularEnumSet ceased to offer performance advantages for small enum types, it could be eliminated from a future release with no ill effects. Similarly, a future release could add a third or fourth implementation of EnumSet if it proved benefi- cial for performance. Clients neither know nor care about the class of the object they get back from the factory; they care only that it is some subclass of EnumSet.
Using constructors instead of static methods like you suggested breaks the factory method pattern, because by using the constructor directly you are specifying an implementation.
In your case, if you want to use a factory method you would make the default constructor private so clients could not directly instantiate a ScoreCard. At this point, you're free to use whatever specific implementation of ScoreCard in the factory method. For example, if you make a second ScoreCard class that is backed with a TreeMap, you can switch which implementation of ScoreCard that the client gets just by changing the static factory.
I have an abstract class Vehicle with 2 implemented subclasses RedVehicle and YellowVehicle.
In another class I have a List<Vehicle> containing instances of both subclasses.
I want to be able to pass into a method a class type and then use that type to decide which set of objects I want to do something to in the List.
Since Class is generic I should parameterise it with something, however putting the parameter as the parent class Vehicle stops the calling code working since exampleMethod is now expecting a type of Vehicle, not a subclass of RedVehicle or YellowVehicle.
I feel there should be a clean way to do this so what would be the correct way to implement the functionality?
n.b. I don't necessarily have to pass in the Class type, if there are better suggestions I'd be happy to try those.
Calling code:
service.exampleMethod(RedVehicle.class);
service.exampleMethod(YellowVehicle.class);
Fields/Method:
//List of vehicles
//Vehicle has 2 subclasses, RedVehicle and YellowVehicle
private List<Vehicle> vehicles;
//Having <Vehicle> as the Class parameter stops the calling code working
public void exampleMethod(Class<Vehicle> type)
{
for(Vehicle v : vehicles)
{
if(v.getClass().equals(type))
{
//do something
}
}
}
Do this instead:
public <T extends Vehicle> void exampleMethod(Class<T> type)
Why don't you use the visitor pattern?
That way you
don't need type tokens
let dynamic dispatch handle the case distinction (instead of if(v.getClass().equals(type)))
are more flexible (following OCP)
In detail:
your abstract class Vehicle gets a method accept(Visitor v), with the subclasses implementing it by calling the appropriate method on v.
public interface Visitor {
visitRedVehicle(RedVehicle red);
visitYellowVehicle(YellowVehicle yellow);
}
Using a visitor:
public class Example {
public void useYellowOnly() {
exampleMethod(new Visitor() {
visitRedVehicle(RedVehicle red) {};
visitYellowVehicle(YellowVehicle yellow) {
//...action
});
}
public void exampleMethod(Visitor visitor){
for(Vehicle v : vehicles) {
v.accept(visitor);
}
}
}
The accepted answer works and got me where I wanted to go. I thought I would add this just to make it clearer to anyone who might need it.
In this case RevisedExposure is a sub-class of Exposure. I need to call GetMetadata() with a list of either of these, which results in the same result set.
private async Task<List<Metadata>> GetMetadata<T>(List<T> exposures) where T : Exposure
Now I can call this method from two places with different versions of the list like this.
var metadata = await GetExposureMetadata(revisions);
or
var metadata = await GetExposureMetadata(exposures);
works great!
Say you have a class Population and Population makes an internal List of Individuals. The user wants to pass an unconstructed Individual subclass to Population and let Population do the work of constructing these, whatever subclass was passed.
public class Population{
private List<Individual> indiList = new ArrayList(25);
/*I know this won't work for multiple reasons, but shows the idea*/
public void addIndividualsOfType(Individual individual){
for (ListIterator it = indiList.listIterator(); it.hasNext(); ){
it.next()
it.add(individual.construct(param1, param2, param3);
}
}
}
public abstract class Individual{
SomeType param1;
...
public Individual(SomeType param1, SomeType param2, SomeType param3){
this.param1 = param1;
...
}
}
public class HappyIndividual extends Individual{
...
}
public class SadIndividual extends Individual{
...
}
I would like to be able to make a call like population.addIndividualsOfType(HappyIndividual)
Obviously, this code will not work for many reasons (like passing an uninstantiated class). I am just trying to illustrate the idea of what I want to do, this is not a question of why the above code does not work. I know it won't work, which is why I can't figure out how one would do such a thing.
I have been messing around with Builders and Static Factory Methods all day. The problem is that we are talking subclasses here. Subclasses don't play well with Static. If I give Individual a static factory method, then I end up creating Individuals, not HappyIndividuals. Similar problems occur with Builder. I also want to keep this not overly complex.
I feel like this should be very easy, but I'm having trouble. Thanks.
There are essentially two ways to do this:
You could continue down your current path and use reflection to construct the classes:
public void addIndividualsOfType(Class<? extends Individual> clazz){
for (ListIterator it = indiList.listIterator(); it.hasNext(); ){
it.next()
it.add(clazz.newInstance()); // using no-args constructor
}
}
and to use a constructor with arguments you'd replaceit.add(clazz.newInstance()) with something like this:
Constructor<? extends Individual> cons = clazz.getConstructor(
param1.getClass(), param2.getClass(), param3.getClass());
it.add(cons.newInstance(param1, param2, param3));
(I've left out the exception handling ... but you get the picture.)
However, an altogether better approach would be to refactor your code so that you passed in a factory object rather than a Class object. For example:
public interface IndividualFactory {
public Individual create(T1 p1, T2 p2, T3 p3);
}
public static final IndividualFactory TALL_FACTORY = new IndividualFactory() {
public Individual create(T1 p1, T2 p2, T3 p3) {
return new TallIndividual(p1, p2, p3);
}
};
public void addIndividualsOfType(IndividualFactory factory){
for (ListIterator it = indiList.listIterator(); it.hasNext(); ){
it.next()
it.add(factory.create(param1, param2, param3);
}
}
Note that the factory-based solution can be statically type-checked. By contrast, the reflective version has to deal with a number of type-related runtime exceptions.
I would like to be able to make a call like population.addIndividualsOfType(HappyIndividual)
You were quite close when you were asking to do that. You can instead pass HappyIndividual.class, which is the class object representing the HappyIndividual class. This object itself is of type Class which represents a class at run-time.
Your method would then look like this:
public void addIndividualsOfType(Class<? extends Invididual> clazz) {
for (ListIterator it = indiList.listIterator(); it.hasNext(); ){
it.next();
it.add(clazz.newInstance());
}
}
The call to newInstance assumes that your class has a default constructor without parameters. Otherwise, you need to use the getConstructor method to obtain a specific constructor and then call newInstance on that constructor with the correct parameters.
Pass in the class in question (e.g., HappyPerson.class) and get the constructor by calling Class.getConstructor(arg...), then instantiate the instance.