The example is as follows: I have a Box that needs to be filled with some Things. I'm interested only in weight of each thing. Also, beside weight, I need to correctly identify the thing that I'm measuring. Each thing type has different Id type. In this case I have toys and fruits, which have ToyId and FruitId respectively. In the end, I need to be able to print thing identifier and thing weight.
Question: Is it somehow possible to access specific methods on ThingIds without using instanceof operator (as in example)?
class Color{}
interface ThingId {}
class FruitId implements ThingId {
String name; //"apple", "orange", ...
FruitId(String name){ this.name = name; }
String getName(){ return this.name; }
}
class ToyId implements ThingId {
String shape; //"square", "circle", ...
Color color; //"red", "blue"...
ToyId(String shape, Color color){ this.shape = shape; this.color = color; }
String getShape(){ return this.shape; }
Color getColor(){ return this.color; }
}
class Thing{
ThingId thingId;
Integer weight;
public Thing(ThingId thingId, Integer weight){
this.thingId = thingId;
this.weight = weight;
}
ThingId getThingId(){ return this.thingId; }
Integer getWeight(){ return this.weight; }
}
class Box {
Set<Thing> things = new HashSet<>();
void addThing(Thing thing){
this.things.add(thing);
}
Collection<Thing> getThings(){
return this.things;
}
}
class Program {
public static void main(String[] args) {
FruitId appleId = new FruitId("apple");
Thing apple = new Thing(appleId, 1);
ToyId cubeId = new ToyId("square", new Color());
Thing cube = new Thing(cubeId, 22);
Box box = new Box();
box.addThing(apple);
box.addThing(cube);
for(Thing t : box.getThings()){
System.out.print("Thing Id is: ");
if(t.getThingId() instanceof FruitId) { //any other possibility than using instance of?
process((FruitId)t.getThingId());
}
if(t.getThingId() instanceof ToyId){ //any other possibility than using instance of?
process((ToyId)t.getThingId());
}
System.out.println("Weight is : " + t.getWeight());
}
}
static void process(FruitId fruitId){
System.out.println(fruitId.getName());
}
static void process(ToyId toyId){
System.out.println(toyId.getShape() + toyId.getColor());
}
}
UPDATE
OK, I think Visitor pattern could be useful here:
class Color{}
interface ThingId {
void visitThingId(ThingIdVisitor visitor);
}
class FruitId implements ThingId {
String name; //"apple", "orange", ...
FruitId(String name){ this.name = name; }
String getName(){ return this.name; }
#Override
public void visitThingId(ThingIdVisitor visitor) {
visitor.process(this);
}
}
class ToyId implements ThingId {
String shape; //"square", "circle", ...
Color color; //"red", "blue"...
ToyId(String shape, Color color){ this.shape = shape; this.color = color; }
String getShape(){ return this.shape; }
Color getColor(){ return this.color; }
#Override
public void visitThingId(ThingIdVisitor visitor) {
visitor.process(this);
}
}
class Thing{
ThingId thingId;
Integer weight;
public Thing(ThingId thingId, Integer weight){
this.thingId = thingId;
this.weight = weight;
}
ThingId getThingId(){ return this.thingId; }
Integer getWeight(){ return this.weight; }
}
class Box {
Set<Thing> things = new HashSet<>();
void addThing(Thing thing){
this.things.add(thing);
}
Collection<Thing> getThings(){
return this.things;
}
}
class ThingIdVisitor{
void process(FruitId fruitId){
System.out.println(fruitId.getName());
}
void process(ToyId toyId){
System.out.println(toyId.getShape() + toyId.getColor());
}
}
class Program {
public static void main(String[] args) {
FruitId appleId = new FruitId("apple");
Thing apple = new Thing(appleId, 1);
ToyId cubeId = new ToyId("square", new Color());
Thing cube = new Thing(cubeId, 22);
Box box = new Box();
box.addThing(apple);
box.addThing(cube);
for(Thing t : box.getThings()){
System.out.print("Thing Id is: ");
t.getThingId().visitThingId(new ThingIdVisitor());
System.out.println("Weight is : " + t.getWeight());
}
}
}
I don't really get what you're trying to achieve. First of all, I don't get the use of the interface ThingId. Second, I think you're a bit confused about interfaces and inheritance. If I were you, I'd look up polymorphism.
Anyway, I propose you remove the ThingId interface and let the FruitId and ToyId classes extend the Thing class. As your collection only exists of Things, and as your Fruit and Toy classes all extend this Thing class and thus implement the getWeight() method, you should not use instanceof anymore.
But please, read up on polymorphism.
your interface ThingId must provide the respective methods that you want to have.
If you simple want to print out information, then you can use like a simple
public String getInformation();
Then the implementations can return the information that is relevant for them and you can simply work with ThingId in your application code.
BTW: As you are storing your Things in a HashSet make sure to implement equals and hashCode in all Thing implementations
Also I dont really see, why you need a Thing and a ThingId, as ThingId seems a bit more than a simple id and actually a thing. So for me it seems that ThingId is redundant and all can be achieved by the having different Things
Since you are calling the same method process on both the instance types, why not add that method to ThingId interface itself.
By doing so, you could just call:
t.getThingId().process();
Instead of finding the instance type and calling respective methods.
Related
I am new to java and I am trying to work a simple program. I have created a class and defined the variables like this
public class Animal {
private String age;
private String color;
Breed breed;
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Breed getBreed() {
return breed;
}
public void setBreed(Breed breed) {
this.breed = breed;
}
}
class Breed {
private String afador;
private String afaird;
private String aussiepom;
public String getAfador() {
return afador;
}
public void setAfador(String afador) {
this.afador = afador;
}
public String getAfaird() {
return afaird;
}
public void setAfaird(String afaird) {
this.afaird = afaird;
}
public String getAussiepom() {
return aussiepom;
}
public void setAussiepom(String aussiepom) {
this.aussiepom = aussiepom;
}
}
I want to access the variables in class "BREED" from ANOTHER file, with "animal.breed..." which does not work. How can I access the variables in the "BREED" class?? I am not sure if it is because I have the getter and setters in this file, kindly advise on the same.
I think I see what you are trying to do, however, you did not provide any sample code so I will be answering based on assumptions.
To start, you are trying to access a variable from inside of the Breed class through the getter methods. Lets look at some code.
// I'm assuming this is similar to what you have set up.
// Make a new breed
Breed breed = new Breed();
// Setting the breed to Afador through your methods
breed.setAfador("Afador");
// Make a new animal
Animal animal = new Animal();
// Set our animal's breed to our newly made breed
animal.setBreed(breed);
You mentioned you got the getBreed() method to work, so you must have done something along the lines of
animal.getBreed();
You then mentioned you could not get getAfaird() method to work, so I assume you did something like this
animal.getAfaird();
This does not work since getAfaird() does not exist within the Animal class but rather the Breed class. You can only use this getAfaird() method on Breed objects. So you would want to do something like this
animal.getBreed().getAfaird();
You must be user the get method:
Animal animal = new Animal();
Breed breed = animal.getBreed();
Another option is declare public the breed attribute, but not is a good practique
Just a question RE: Constructor Chaining in subclasses that I can't find a good answer on and I'm confusing myself a bit with.
I'm making a basic little Text Based RPG for some practice and I'm going through my constructors for an abstract class and have the constructors from 0-4 params chained together like below
abstract class Creature {
// Fields
private String name;
private int lifeForce;
private int strength;
private int agility;
// Constructors + Chaining
public Creature() {
this("Unknown")
}
public Creature(String name) {
this(name, 100);
}
public Creature(String name, int lifeForce) {
this(name, lifeForce, 10);
}
public Creature(String name, int lifeForce, int strength) {
this(name, lifeForce, strength, 10);
}
public Creature(String name, int lifeForce, int strength, int agility) {
this.name = name;
this.lifeForce = lifeForce;
this.strength = strength;
this.agility = agility;
}
My confusion is how best to format the constructors of a subclass of creature, for example this simple Person class introduces two new fields. There's definitely too much repetition if I write the constructors like this
// Constructors + Chaining
public Person() {
super("Unknown");
this.skillClass=new Mage();
this.dialogue="...";
}
public Person(String name) {
super(name);
this.skillClass=new Mage();
this.dialogue="...";
} etc etc etc
I suppose I could restrict the constructors to limit the repetition but I'm mostly just wondering if there's good best practice that I'm missing here.
Any and all suggestions welcome and if anyone has any good resources to recommend that go deeper than the usual
Class B extends Class A
examples I'd massively appreciate.
In situations like this one when you need to use multiple constructors with different parameters, it is recommended to use the builder pattern like this :
abstract class Creature {
// Fields
private String name;
private int lifeForce;
private int strength;
private int agility;
private Creature(Builder<?> builder) {
this.name = builder.name;
this.lifeForce = builder.lifeForce;
// Add the other attributes here.
}
public static abstract Builder extends Builder<T extends Builder<T>> {
private String name;
private int lifeForce;
private int strength;
private int agility;
public Builder(//here you put the attributes that you need to have in all instances) {
// here you do the affectations.
}
// now you need to make the functions that set each property :
public Builder lifeForce(int lifeForce) {
this.lifeForce = lifeForce;
return this;
}
// you do the same thing for all the other attributes.
...
public Creature build() {
return new Creature(this);
}
}
}
So for the explanation : This pattern will allow you to create instances of your class by setting only the needed attributes.
As here you have subclasses the builder pattern will be little bit more harder to understand but it is the perfect solution in such situation.
We need to apply the builder pattern also for every subclasse so let's do it for the person class :
public class Person extends Creature {
private int anotherField;
public Person(Builder builder) {
super(builder);
this.anotherField = anotherField;
}
public static Builder extends Creature.Builder<Builder> {
public Builder(//add the fieldHere if it is needed in all class instances) {
// if the field is not mandatory you can omit this constructor but you need to put the function below.
}
public Builder anotherField(int anotherField) {
this.anotherField = anotherField;
}
public Person build() {
return new Person(this);
}
}
Now let me show you how tricky is this solution :
1/ declare person with 2 fields :
Person p1 = Person.Builder().name("name").anotherField(0).build();
2/ declare another one with just one field
Person p2 = Person.Builder().agility(1000).build();
Remark : In these two examples, i supposed that your builders' constructors don't have parameters. If for example the name is mandatory field :
Person p3 = Person.Builder("name").anotherField(0).build();
I wish that you had the idea about using builder pattern.
I'm writing a game, as part of this players should be able to click on various GUI items and see further details on a specific area of the GUI. I'm mangaing this through an interface Detailable which is implemented by suitable game obects and sends the appropriate information to the JPanel
There are also containers (all of which implement Detailable) that contain other (Detailable implementing) objects. The goal being it is possible to click on a container and, amongst its stats, see its contents which can then be in turn clicked on to see their stats, etc.
The problem I am having is in writing the addToContents(Detailable d) method of my containers. Each container as an ArrayList<String> of the "type" of container - wardrobe, bookcase, etc. I want to be able to add only certain classes to a given container - so a container with a type of "bookcase" will only accept objects of class Book or Curio for example.
What I currently have is:
public boolean addToContents(Detailable d){
if(this.types.contains("bookcase") && d.getClass().getName().equals("Book")){
//do some stuff
//I know "Book" isn't the right syntax, this is just to demo
return true;
}
else if(this.types.contains("bookcase") && d.getClass().getName().equals("Curio")){
//other stuff
return true;
}
//etc
else{
return false;
}
}
But this feels like the wrong way of doing it. Is there a better way? Ideally, for sake of easy code, I'd have something like (pseudocode)
Constructor:
private ArrayList<Class> classesAccepted = <list of classes>
addToContents:
if (classesAccepted.contains(d.getClass()){
add the thingie to contents
return true
}
else{
return false;
}
but I can't seem to find a way of adding a list of classes to the constructor - of translating the ArrayList of class names to an ArrayList of references to the actual class.
Containers are currently read from a JSON so comprise two classes:
public class FurnitureType {
private String name;
private List<String> type;
private int cost;
private String description;
private int comfortBonus;
private int capacity;
//plus getters for all the above
}
public class Furniture implements Detailable, ListSelectionListener{
private String name;
private List<String> types;
private int cost;
private String description;
private int comfortBonus;
private int capacity;
private ArrayList<Detailable> contents;
private transient DetailPanel dp = null;
public Furniture (FurnitureType type){
this.name=type.getName();
this.types = type.getType();
this.cost = type.getCost();
this.description = type.getDescription();
this.comfortBonus = type.getComfortBonus();
this.capacity = type.getCapacity();
this.contents = new ArrayList();
}
//appropriate getters
public boolean addToContents(Detailable d){
if(this.types.contains("bookcase") && d.getClass().getName().equals("Book")){
//do some stuff
//I know "Book" isn't the right syntax, this is just to demo
return true;
}
else if(this.types.contains("bookcase") && d.getClass().getName().equals("Curio")){
//other stuff
return true;
}
//etc
else{
return false;
}
}
#Override
public String toString(){
return description;
}
#Override
public Icon getBigPic() {
return null;
}
#Override
public JComponent getStats() {
Object [] objectContents = contents.toArray();
JList contentList = new JList(objectContents);
contentList.setPreferredSize(new Dimension (400, 300));
contentList.setFixedCellHeight(50);
contentList.addListSelectionListener(this);
contentList.setCellRenderer(new CustomCellRenderer());
//the CustomCellRenderer class simply makes long descriptions into multiline cells
return contentList;
}
#Override
public void addPanel(DetailPanel dp) {
this.dp = dp;
}
#Override
public void valueChanged(ListSelectionEvent lse) {
Detailable d = contents.get(lse.getFirstIndex());
dp.updatePanel(d);
}
You can actually use a Map as shown below:
private static Map<String, List<Class<? extends Detailable>>>
bookcaseContainer = new HashMap<>();
static {
//load the bookcaseContainer Map from properties/database
bookcaseContainer.put("bookcase", list1);
bookcaseContainer.put("wardrobe", list2);
}
if(bookcaseContainer.get("bookcase") != null &&
bookcaseContainer.get("bookcase").contains(d.getClass())) {
//do something here
} else if(bookcaseContainer.get("wardrobe") != null &&
bookcaseContainer.get("wardrobe").contains(d.getClass())) {
//do something here
}
If I understand your question correctly, you are looking for something like this
ArrayList <Class<? extends Detailable>> acceptedClasses = new ArrayList<>();
acceptedClasses.add(Bookcase.class);
acceptedClasses.add(OtherAcceptable.class);
and then do something akin to
boolean test =
acceptedClasses.stream().anyMatch(clazz -> aClass.isInstance(detailableInstance));
to check if the instance is of an acceptable type
I want to find the difference between two Set<T> using a different equality metric than that used by the class T, for example a custom Comparator<T>
For example, I have a class Animal, which usually tests equality using the species of the Animal
public class Animal {
public String species;
public String genus;
public Animal(String species, String genus){
this.species = species;
this.genus = genus;
}
public boolean equals(Animal other){
return other.species.equals(this.species);
}
}
I have two List<Animal> and I'd like to find the intersection of shared genus between the two lists.
Usually, I'd convert the List to Set and use retainAll to find the intersection. But here, that would give the intersection of shared species, not shared genus.
I'd like to use something like the GenusComparator to define equality for the intersection.
public class GenusComparator implements Comparator<Animal>{
#Override
public int compare(Animal animal1, Animal animal2) {
return String.CASE_INSENSITIVE_ORDER.compare(animal1.genus, animal2.genus);
}
}
This is just a simple example to explain what I'm trying to do, not the actual classes in my application.
Two possible solutions that I have found are
Wrap the class and override the equals method
Use a TreeSet with a custom Comparator
Are there other ways I've missed so far, and what are the possible pros and cons of these solutions?
The easiest way to do it, is to simple use a TreeSet with the GenusComparator.
You have to convert both sets to TreeSet(GenusComparator) for the retainAll() to work correctly.
I fixed equals() and added hashCode() and toString().
public class Test {
public static void main(String[] args) {
Set<Animal> set1 = new HashSet<>(Arrays.asList(new Animal("Jaguar", "Panthera"),
new Animal("Margay", "Leopardus"),
new Animal("Tiger", "Panthera")));
Set<Animal> set2 = new HashSet<>(Arrays.asList(new Animal("Bobcat", "Lynx"),
new Animal("Cougar", "Puma"),
new Animal("Leopard", "Panthera")));
TreeSet<Animal> treeSet1 = new TreeSet<>(new GenusComparator());
treeSet1.addAll(set1);
TreeSet<Animal> treeSet2 = new TreeSet<>(new GenusComparator());
treeSet2.addAll(set2);
treeSet1.retainAll(treeSet2);
System.out.println(treeSet1);
}
}
class Animal {
public String species;
public String genus;
public Animal(String species, String genus) {
this.species = species;
this.genus = genus;
}
#Override
public boolean equals(Object obj) {
return obj instanceof Animal && this.species.equals(((Animal)obj).species);
}
#Override
public int hashCode() {
return this.species.hashCode();
}
#Override
public String toString() {
return this.species + "/" + this.genus;
}
}
class GenusComparator implements Comparator<Animal> {
#Override
public int compare(Animal animal1, Animal animal2) {
return String.CASE_INSENSITIVE_ORDER.compare(animal1.genus, animal2.genus);
}
}
Output
[Jaguar/Panthera]
I'm writing a library, which has a predefined set of values for an enum.
Let say, my enum looks as below.
public enum EnumClass {
FIRST("first"),
SECOND("second"),
THIRD("third");
private String httpMethodType;
}
Now the client, who is using this library may need to add few more values. Let say, the client needs to add CUSTOM_FIRST and CUSTOM_SECOND. This is not overwriting any existing values, but makes the enum having 5 values.
After this, I should be able to use something like <? extends EnumClass> to have 5 constant possibilities.
What would be the best approach to achieve this?
You cannot have an enum extend another enum, and you cannot "add" values to an existing enum through inheritance.
However, enums can implement interfaces.
What I would do is have the original enum implement a marker interface (i.e. no method declarations), then your client could create their own enum implementing the same interface.
Then your enum values would be referred to by their common interface.
In order to strenghten the requirements, you could have your interface declare relevant methods, e.g. in your case, something in the lines of public String getHTTPMethodType();.
That would force implementing enums to provide an implementation for that method.
This setting coupled with adequate API documentation should help adding functionality in a relatively controlled way.
Self-contained example (don't mind the lazy names here)
package test;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<HTTPMethodConvertible> blah = new ArrayList<>();
blah.add(LibraryEnum.FIRST);
blah.add(ClientEnum.BLABLABLA);
for (HTTPMethodConvertible element: blah) {
System.out.println(element.getHTTPMethodType());
}
}
static interface HTTPMethodConvertible {
public String getHTTPMethodType();
}
static enum LibraryEnum implements HTTPMethodConvertible {
FIRST("first"),
SECOND("second"),
THIRD("third");
String httpMethodType;
LibraryEnum(String s) {
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
static enum ClientEnum implements HTTPMethodConvertible {
FOO("GET"),BAR("PUT"),BLAH("OPTIONS"),MEH("DELETE"),BLABLABLA("POST");
String httpMethodType;
ClientEnum(String s){
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
}
Output
first
POST
Enums are not extensible. To solve your problem simply
turn the enum in a class
create constants for the predefined types
if you want a replacement for Enum.valueOf: track all instances of the class in a static map
For example:
public class MyType {
private static final HashMap<String,MyType> map = new HashMap<>();
private String name;
private String httpMethodType;
// replacement for Enum.valueOf
public static MyType valueOf(String name) {
return map.get(name);
}
public MyType(String name, String httpMethodType) {
this.name = name;
this.httpMethodType = httpMethodType;
map.put(name, this);
}
// accessors
public String name() { return name; }
public String httpMethodType() { return httpMethodType; }
// predefined constants
public static final MyType FIRST = new MyType("FIRST", "first");
public static final MyType SECOND = new MyType("SECOND", "second");
...
}
Think about Enum like a final class with static final instances of itself. Of course you cannot extend final class, but you can use non-final class with static final instances in your library. You can see example of this kind of definition in JDK. Class java.util.logging.Level can be extended with class containing additional set of logging levels.
If you accept this way of implementation, your library code example can be like:
public class EnumClass {
public static final EnumClass FIRST = new EnumClass("first");
public static final EnumClass SECOND = new EnumClass("second");
public static final EnumClass THIRD = new EnumClass("third");
private String httpMethodType;
protected EnumClass(String name){
this.httpMethodType = name;
}
}
Client application can extend list of static members with inheritance:
public final class ClientEnum extends EnumClass{
public static final ClientEnum CUSTOM_FIRST = new ClientEnum("custom_first");
public static final ClientEnum CUSTOM_SECOND = new ClientEnum("custom_second");
private ClientEnum(String name){
super(name);
}
}
I think that this solution is close to what you have asked, because all static instances are visible from client class, and all of them will satisfy your generic wildcard.
We Fixed enum inheritance issue this way, hope it helps
Our App has few classes and each has few child views(nested views), in order to be able to navigate between childViews and save the currentChildview we saved them as enum inside each Class.
but we had to copy paste, some common functionality like next, previous and etc inside each enum.
To avoid that we needed a BaseEnum, we used interface as our base enum:
public interface IBaseEnum {
IBaseEnum[] getList();
int getIndex();
class Utils{
public IBaseEnum next(IBaseEnum enumItem, boolean isCycling){
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
if (index + 1 < list.length) {
return list[index + 1];
} else if(isCycling)
return list[0];
else
return null;
}
public IBaseEnum previous(IBaseEnum enumItem, boolean isCycling) {
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
IBaseEnum previous;
if (index - 1 >= 0) {
previous = list[index - 1];
}
else {
if (isCycling)
previous = list[list.length - 1];
else
previous = null;
}
return previous;
}
}
}
and this is how we used it
enum ColorEnum implements IBaseEnum {
RED,
YELLOW,
BLUE;
#Override
public IBaseEnum[] getList() {
return values();
}
#Override
public int getIndex() {
return ordinal();
}
public ColorEnum getNext(){
return (ColorEnum) new Utils().next(this,false);
}
public ColorEnum getPrevious(){
return (ColorEnum) new Utils().previous(this,false);
}
}
you could add getNext /getPrevious to the interface too
#wero's answer is very good but has some problems:
the new MyType("FIRST", "first"); will be called before map = new HashMap<>();. in other words, the map will be null when map.add() is called. unfortunately, the occurring error will be NoClassDefFound and it doesn't help to find the problem. check this:
public class Subject {
// predefined constants
public static final Subject FIRST;
public static final Subject SECOND;
private static final HashMap<String, Subject> map;
static {
map = new HashMap<>();
FIRST = new Subject("FIRST");
SECOND = new Subject("SECOND");
}
private final String name;
public Subject(String name) {
this.name = name;
map.put(name, this);
}
// replacement for Enum.valueOf
public static Subject valueOf(String name) {
return map.get(name);
}
// accessors
public String name() {
return name;
}