I have a task that needs to be done but I am really stuck.
Basically, I've some inheritance relations like this:
Animal
Pet WildAnimal
Bird Cat Dog Fish ||Snake Eagle
Animal is the parent of Pet and Wild Animal.
Pet is the parent of Bird, Cat, Dog, Fish.
WildAnimal is the parent of Snake and Eagle.
The task wants me to read inputs from a file which is "input.txt" and create Animal objects.
"input.txt" is like:
kiwi Bird
charlie Eagle
mango Fish
pepper Dog
angle Cat
tweety Bird
bob Dog
ziggy Snake
I can get all of the names but I couldn't figure out how to understand which kind of object every single name represent.
Here is the main method:
public static void main(String[] args) throws IOException {
String s ="";
int nameCounter = 0;
Animal[] animals = new Animal[100];
try{
Scanner input = new Scanner(Paths.get("input.txt"));
while (input.hasNext()) {
s = input.next();
Animal animal = new Animal(s);
animals[nameCounter] = animal;
nameCounter += 2;
}
}catch(Exception e){
e.printStackTrace();
}
}
Here is the animal class:
public class Animal {
private String name;
private int numberOfLegs;
private int numberOfWings;
public Animal(String name){
this.name = name;
numberOfLegs = 4;
numberOfWings = 0;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNumberOfLegs() {
return numberOfLegs;
}
public void setNumberOfLegs(int numberOfLegs) {
this.numberOfLegs = numberOfLegs;
}
public int getNumberOfWings() {
return numberOfWings;
}
public void setNumberOfWings(int numberOfWings) {
this.numberOfWings = numberOfWings;
}
public void talk(){
System.out.printf("<Silence>");
}
public void fly(){
System.out.printf("%s cannot fly", getName());
}
public void run(){
System.out.printf("%s is running", getName());
}
}
I can add all the other classes if you want but i don't think you're gonna need them.
You have to instantiate objects of your specific class; based on the incoming string.
Example: if the class name from the file is Bird ... then you have to call new Bird() somehow.
There are two ways to get there:
Using reflection (you can actually instantiate classes "by string"; without knowing anything about that class)
By using a switch statement
Reflection is more of an "advanced" topic (and very easy to use the wrong); so I really do recommend you to go for option 2, like:
private Animal createAnimalFor(String className, String animalName) {
switch (className) {
case "Bird": return new Bird(animalName);
...
default: throw new IllegalArgumentException("Dont know how to create object for unknown class: " + className);
}
}
(the above code is meant as "fyi" - I didn't run it through the compiler; it is meant to give you one idea how this could be done).
Some notes beyond that:
Consider using a final field for those properties of your objects that can't change. You don't need a setter for the name then; just give the name as parameter to the constructor. In other words: only make those fields "changeable" that make sense to be changed. Anything else should better be final.
Instead of using an array with 100 empty slots, you could use a java.util.ArrayList and just add as many new animals as you find in that file.
Consider adding equals/hashCode methods to your Animal class (not mandatory, but you should read why that makes sense very often).
Probably most importantly: consider not putting all those different methods directly into your base class. It might make more sense to create either abstract subclasses that add certain functions, or use interface, like interface FlyingAnymal { void fly() }; which your specific subclasses would then implement. It is not really good practice to put a lot of methods on your base class ... that simply dont make sense for all of the sub classes.
If you really want to use reflection to do so (which I would also discourage), here's sample code :
String name = input.next();
String className = input.next();
// apply transformations to className as needed
Class<Animal> c = (Class<Animal>) Class.forName(className);
Constructor<Animal> constr = c.getDeclaredConstructor(String.class); // retrieves the Animal(String name) constructor
Animal a = constr.newInstance(name);
I don't think the code is so complex, but few people have ever used reflection so they'll have problems maintaining it, and it is tightly coupled with your classes definitions so it will probably have to be maintained a lot.
Related
I'm working on a problem where different animal types implement the same talk() method from Animal interface.
If you look at getAnimal() method, you can see that, when a new kind of animal is added to the program, inside of that method has to be changed as well.
I want to add new animals just by subclassing Animal without changing anything in the already existing classes.
For example, add an animal "Dog", criteria="loyal"; talk="woof".
Could you tell me, how it is possible? Below is my code:
interface Animal {
public void talk();
}
class Lion implements Animal {
#Override
public void talk() {
System.out.println("ROARRRRR");
}
}
class Mouse implements Animal {
#Override
public void talk() {
System.out.println("SQUEEEEEAK");
}
}
class Bison implements Animal {
#Override
public void talk() {
System.out.println("BELLOWWWWW");
}
}
class AnimalType {
public static Animal getAnimal(String criteria) {
// I refactor this method
if (criteria.equals("small")) {
return new Mouse();
} else if (criteria.equals("big")) {
return new Bison();
} else if (criteria.equals("lazy")) {
return new Lion();
}
return null;
}
}
public class AnimalExamples {
public static void main(String[] args) {
AnimalType.getAnimal("small").talk();
AnimalType.getAnimal("big").talk();
AnimalType.getAnimal("lazy").talk();
// how to add an animal "Dog" here, criteria="loyal"; talk="woof"
AnimalType.getAnimal("loyal").talk();
try {
AnimalType.getAnimal("small").talk();
} catch (Exception ex) {
System.out.println("Animal does not exists");
}
}
}
I searched on google, understood it can be done by reflection. But do not know how. If possible, could you help me with this, please? Thanks in advance!
Just so you know runtime class generation is extremely complex and not something recommended for beginners to the language. This would be an excellent scenario to use a map an anonymous classes.
class AnimalType {
private static final Map<String, Animal> animals = new HashMap<String, Animal>();
static {
// Populating map with default animals
addAnimal("big","BELLOWWWWW"); // bison
addAnimal("small","SQUEEEEEAK"); // mouse
addAnimal("lazy","ROARRRRR"); // lion
addAnimal("loyal","WOOF "); // dog
}
public static void addAnimal(String criteria, final String sound) {
// Assigning a anonymous implementation of animal to the given criteria
animals.put(criteria, new Animal() {
#Override
public void talk() {
System.out.println(sound);
}
});
}
public static Animal getAnimal(String criteria) {
// Returning an animal from the animals map
return animals.get(criteria);
}
}
If you really do insist on true runtime class generation or if you're curious how it works, check out ByteBuddy.
Old question, but here is how to create class... For me the easy way is to use Javassist.
I created a small example here: http://hrabosch.com/2018/04/08/generate-class-during-runtime-with-javassist/
But here is main point:
public static Class generateClass(String className, String methodName, String methodBody)
throws CannotCompileException {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass(className);
StringBuffer method = new StringBuffer();
method.append("public void ")
.append(methodName)
.append("() {")
.append(methodBody)
.append(";}");
cc.addMethod(CtMethod.make(method.toString(), cc));
return cc.toClass();
}
So what I did... Via Javassist I made a class in ClassPool. Also I added a method inside this class and via reflection I invoked it.
Hope it helps.
Just keep on mind whatever you want to use in generated class, there
are NOT imports, so you have to use fully-qualified names.
Java doesn't support creating a class at runtime. However there are really better ways of achieving what you want here. I'll propose two.
Firstly, you could create an AnimalType class that contains all the shared behaviour about a species. You could then have an Animal class that takes an AnimalType as a constructor parameter.
Secondly, you could use a prototype design pattern. In this case the Animal class would need a clone method to create a new animal from the prototype. The factory class could then have a list of the prototypes and use whatever logic you desire to choose the correct prototype to clone.
Comment below if you want further details or sample code for either of these options.
you have to define the dog class
class Dog implements Animal {
#Override
public void talk() {
System.out.println("woof");
}
}
and add the if else to AnimalType
} else if ("loyal".equals(criteria)) {
return new Dog();
}
Okay, I want to start off my question with an example of what I'd basically like to do, though it's not working this way.
I want to have an interface IDog that enforces its implementations to have some methods. I also want an superclass AbstractDog implements IDog to give basic attributes and methods to all Dog classes. Then I want to have Subclasses like Poodle extends AbstractDog. My problem here are static methods - I basically want each subclass of AbstractDog to have a different static method but I want to be able to enforce this method from IDog.
So my naïve (and wrong) implementation would be:
public interface IDog {
String getName(); // every dog instance should be able to call name
static String getDescription(); // every dog class should be able to get its description
}
public abstract class AbstractDog implements IDog {
private String name; // every dog instance will have this
public AbstractDog(String name) {
this.name = name;
}
#Override
public String getName() {
return this.name; // every dog instance can call this
}
}
public class Poodle extends AbstractDog {
private static String description = "It's a poodle!"; // all Poodles have the same description
public Poodle(String name) {
super(name);
}
#Override // from IDog
public static String getDescription() {
return description;
}
}
Now, as I said, this is not correct because the AbstractDog class would need a static abstract method getDescription() and IDog needs an implementation of its method and it can't be overridden.
I want to know, if there is a Design pattern which matches my problem: enforcing a set of classes (which could or should have an intermediate superclass) to implement a (different!) static method.
One possibility I have discovered, but I'm not sure if it may be useful or even adequate, would be the use of an enum DogType and then just having a class Dog with a DogType attribute:
public enum DogType {
Poodle("This is a poodle."), Havanese("This is a Havanese.)";
private String description;
private DogType(String description) {
this.description = description;
}
public String getDescription() {
return this.description;
}
}
public class Dog {
private String name;
private DogType dogType;
public Dog(String name, DogType dogType) {
this.name = name;
this.dogType = dogType;
}
public String getName() {
return this.name;
}
public String getDescription {
return this.dogType.getDescription();
}
}
However, this "workaround" loses an ability over my initial idea: I now can't additional functionalities to only one dog class like an instance method void prance() which should only be accessible to Poodle.
Many topics regarding similar questions have refered to the Factory pattern, but I'm not sure how it fits my problem because I don't necessarily need a constructing method. And as the number of dog races rises my code would become very confusing I think. Or maybe I just didn't get how the Factory should be used correctly in my case.
Interfaces are enforced behaviours. Classes are used to specify properties. Static methods get hidden. They are not over-ridden by subclasses. So if you have static methods in your subclasses, but your object reference is of supertype class, then your static method from superclass is invoked. This is class Method hiding, happens with static methods.
I want to know, if there is a Design pattern which matches my problem:
enforcing a set of classes (which could or should have an intermediate
superclass) to implement a (different!) static method.
Sorry. Static methods and inheritance don't go hand in hand.
I now can't additional functionalities to only one dog class like an
instance method void prance() which should only be accessible to
Poodle.
You could introduce a interface Prancable with method void prance().
public interface Prancable{
void prance();
}
public class Poodle extends Dog implements Prancable{
#Override
public void prance(){
System.out.println("My Poodle can prance.");
}
}
You can proceed in this manner for specific methods that add behaviour to different dog breeds.
This is a code smell, there is likely a better way to do it.
If the static method will always return the same thing for all objects of the class, you should just make it a regular get method.
#Override \\ from IDog
public String getDescription() {
return "This is a poodle";
}
If the static variable may be changed then make a new object that holds this class-wide state and give it to each class in the constructor.
ex.
// StringState is a new class that holds a string and has a set and get method
StringState desc = new StringState("original description");
IDog dog1 = new Poodle(desc);
IDog dog2 = new Poodle(desc);
// prints original description
System.out.Println(dog1.getDescription());
System.out.Println(dog2.getDescription());
desc.set("New description");
// prints new description, since both objects share the same
// StringState,changing it here changes it in all of them.
System.out.Println(dog1.getDescription());
System.out.Println(dog2.getDescription());
I'm not sure if these question is still appropriate to be asked as there could be an answer already. But i still dont understand the concept of inheritance when it comes to attributes in parent and child class relationship. Please note the example below.
class Animal{
public int lifeSpan = 50;
public String imAn(){
return "I'm an Animal";
}
}
class Elephant extends Animal{
public int lifeSpan = 100;
public String imAn(){
return "I'm an Elephant";
}
}
public class Test{
public static void main(String args[]){
Animal animal = new Elephant();
System.out.println(animal.imAn()+" and i live around "+animal.lifeSpan+" years");
}
}
Answer would be : I'm an Elephant and i live around 50 years.
I do understand the virtual method invocation concept here, but what makes it not load the lifeSpan attribute of child class. Does this means the class attributes are not polymorphic?
Does this means the class attributes are not polymorphic?
No, fields aren't polymorphic. You've actually got two fields in your Elephant class - one declared in Animal and one declared in Elephant, which hides the one in Animal. That's the problem. You should get rid of the declaration of lifeSpan in Elephant, and instead initialize the one remaining field in a constructor.
You should also get into the habit of making fields private - and final, where possible. Assuming you really want to have a method to describe the name (rather than a field, which would be more usual) I would write your code as:
class Animal {
private final int lifeSpan;
public Animal() {
// Default to a life-span of 50
this(50);
}
public Animal(int lifeSpan) {
this.lifeSpan = lifeSpan;
}
public String getName(){
return "Animal";
}
public int getLifeSpan() {
return lifeSpan;
}
}
class Elephant extends Animal {
public Elephant() {
// Give every elephant a life-span of 100.
super(100);
}
#Override public String getName() {
return "Elephant";
}
}
public class Test {
public static void main(String args[]){
Animal animal = new Elephant();
System.out.printf("I am an %s and I live around %d years%n",
animal.getName(), animal.getLifeSpan());
}
}
I know several programming languages. Most of them are scripting languages like lua, perl, JS, ruby, etc.
But recently, I started programming in Java, which works quietly. So I have been thinking of a certain function that exists in JS. The prototype of constructors, that is. For further understanding of what my question really is, I will make an example in JS. Let's say you want to create an application of dogs.
function dog (){
this.property1 = value;
this.propertr2 = value2;
this.propertyN = valueN;
//etc.
}
//now, I will create several instances of the constructor in JS
var snoopy = new dog();
var buddy = new dog();
and the awesome part, that I know about JS is that you can dynamically change the information of the constructor and all of the instances that is of the constructor (as it is called in JS) with the prototype keyword like this:
dog.prototype.bark = function () {
console.log("Woof!");
};
and THIS, does not only change the information about the constructor so that every dog that will ever be created with the constructor will know how to bark, it also changes so that all of the instances of the constructor gets the information of the prototype insertion which in this case teaches the dogs how to bark. which we can see in the next example:
var someOtherDog = new dog ();
someOtherDog.bark(); //output will be: Woof!
snoopy.bark(); //output will also be: Woof!
buddy.bark(); //you guessed it! it will also be: Woof!
So with this prototype keyword in JS I can manipulate constructors and their instances. Now, my question is:
HOW can I manipulate the classes and their instances in java? And is that even possible?
and if so; what should I do in order to do anything like that in java?
class dog
{
private String hairColor;
public dog ()
{
hairColor = "Brown";
}
public static void main (String args[])
{
dog snoopy = new dog ();
dog buddy = new dog ();
//now, how do I manipulate the class like I did in JS?
}
}
The thing is that both lua and JavaScript are prototype based, Java is not. You can use reflection to accomplish something similar, but not at the level of JavaScript. Reflection
Inheritance in JavaScript is accomplished by the prototype chain. Basically, when bark is not found in the snoopy object, it is looked up in its prototype snoopy.prototype. If it is found there, that version is used. If not (for example when calling bark.toString()), the prototype chain is traversed until a prototype is found which has that member. The prototype itself is shared between all 'instances' and since it's just a normal object, you can add or remove members to it later on.
Inheritance in Java is class-based. You cannot add or remove members from a class definition at run time unless you recompile and reload the whole class. It's a different programming paradigm which means that you'll have to program (slightly) differently for it using other techniques and patterns.
You can create anonymous classes on the fly if you want.
Say you have a class:
class Dog {
String name;
Dog(String name) { this.name = name; }
void bark() { System.out.println(name + " says 'woof!'"); }
public static void main(String...args) {
Dog snoopy = new Dog("snoopy");
snoopy.bark();
}
}
Here's the result
c:\files\j>javac Dog.java
c:\files\j>java Dog
snoopy says 'woof!'
Now buddy he doesn't say woof - he says ruff! So we create one on the fly like so
class Dog {
String name;
Dog(String name) { this.name = name; }
void bark() { System.out.println(name + " says 'woof!'"); }
public static void main(String...args) {
Dog snoopy = new Dog("snoopy");
snoopy.bark();
Dog buddy = new Dog("buddy") {
#Override void bark() { System.out.println(name + " says 'ruff!'"); }
};
buddy.bark();
}
}
Which results in
c:\files\j>javac Dog.java
c:\files\j>java Dog
snoopy says 'woof!'
buddy says 'ruff!'
If you wanted to permanently change every dog, that becomes more difficult, but can be done via the strategy pattern.
Let's say we have the following
abstract class BarkingStrategy {
public abstract void doBark(Dog dog);
}
class TypicalBarkingStrategy extends BarkingStrategy {
public void doBark(Dog dog) { System.out.println(dog.getName() + " says 'woof!'"); }
}
class AggressiveBarkingStrategy extends BarkingStrategy {
public void doBark(Dog dog) { System.out.println(dog.getName() + " says 'Rrrruff!'"); }
}
class Dog {
// notice this is static - that means it belongs to the class itself, not
// any particular instance of it - similar to prototype
static BarkingStrategy bark = new TypicalBarkingStrategy();
String name;
Dog(String name) { this.name = name; }
String getName() { return name; }
void bark() { bark.doBark(this); }
}
Then you can do the following
public static void main(String...args) {
Dog snoopy = new Dog("snoopy");
snoopy.bark();
Dog.bark = new AggressiveBarkingStrategy();
snoopy.bark();
}
This results in
c:\files\j>javac Dog.java
c:\files\j>java Dog
snoopy says 'woof!'
snoopy says 'Rrrruff!'
I made a similar question a few days ago, but now I have new requirements, and new challenges =). As usual, I'm using the animal enums for didactic purposes, once I don't want to explain domain-specific stuff
I have a basic enum of animals, which is used by the whole zoo (I can add stuff to it, but must keep compatibility):
public enum Animal {
DOG,
ELEPHANT,
WHALE,
SHRIMP,
BIRD,
GIRAFFE;
}
I need to categorize them in a few, non-related categories, like gray animals (whale (my whale is gray) and elephant), small animals (bird, shrimp and dog), sea animals (whale and shrimp).
I could, as suggested in my previous questions, add a lot of booleans, like isGray, isSmall and isFromSea, but I'd like an approach where I could keep this somewhere else (so my enum doesn't need to know much). Something like:
public enum Animal {
DOG,
ELEPHANT,
WHALE,
SHRIMP,
BIRD,
GIRAFFE;
public boolean isGray() {
// What comes here?
}
}
Somewhere else
public enum GrayAnimal {
WHALE,
ELEPHANT;
}
How is this possible? Am I requesting too much from Java?
Did you try EnumSet or EnumMap?
You can create a method
Set<Animal> grayAnimals(){
return EnumSet.of(Animal.WHALE, Animal.ELEPHANT);
}
I think it would be best to store such properties in the enum instances themselves, i.e.
public enum Animal {
DOG(NOT_GRAY),
ELEPHANT(GRAY),
WHALE(GRAY),
SHRIMP(NOT_GRAY),
BIRD(NOT_GRAY),
GIRAFFE(NOT_GRAY);
private static boolean GRAY = true;
private static boolean NOT_GRAY = !GRAY;
private Animal(boolean isGray) {
// snip
}
}
You could even encode several boolean properties into one byte (or use BitSet instead);
public enum Animal {
DOG(),
ELEPHANT(GRAY | BIG),
WHALE(GRAY | BIG),
SHRIMP(),
BIRD(),
GIRAFFE(BIG);
private static byte GRAY = 0x01;
private static byte BIG = GRAY << 1;
private final byte _value;
private Animal() {
this(0x00);
}
private Animal(byte value) {
_value = value;
}
public boolean isGray() {
return _value & GRAY != 0x00;
}
public boolean isBig() {
return _value & BIG != 0x00;
}
}
Nevertheless, what about simply doing this:
public class GrayAnimal {
public static final Animal ELEPHANT = Animal.ELEPHANT;
public static final Animal WHALE = Animal.WHALE;
}
or something like this
public enum Animal {
DOG,
ELEPHANT,
WHALE,
SHRIMP,
BIRD,
GIRAFFE;
// thanks to Mihir, I would have used a regular HashSet instead
public static final Set<Animal> GRAY = Collections.unmodifiableSet(EnumSet.of(ELEPHANT, WHALE));
}
Remember that enums are only useful when you need to differentiate objects in your code--they are useless except that they can be typed in as code.
This is relevant because you are introducing elements into your software that will turn out to be bad code smells in the long run.
For instance, how do you use these except in statements like:
if(critter.type == WHALE)
critter.movement=WATER;
else if(critter.type == ELEPHANT)
This should instantly alert any OO programmer--switches are a bad code smell since they almost always indicate bad OO design).
The alternative is to create a finite set of objects, initialized by data, preferably not code.
You might have an instance of critter with the attributes of a whale--perhaps whale.move() would use an instance of WaterMovement whereas the elephant contains and uses an instance of LandMovement.
In general, programming in OO instead of using switches and enums will collapse an amazing amount of code.
Every time you write a method, remember the mantra "Don't ask an object for data and then operate upon the object, instead ask the object to do an operation for you".
I don't know why you want to put it in another enum, when you could put it in that function:
public boolean isGray() {
return this == WHALE || this == ELEPHANT;
}
maybe something like this:
package p;
import java.util.*;
enum Type {
small,big,grey;
}
enum Animal {
bird(EnumSet.of(Type.small)),whale(EnumSet.of(Type.big, Type.grey)),elephant(EnumSet.of(Type.big, Type.grey));
Animal(final EnumSet<Type> types) { this.types=types; }
EnumSet<Type> types=EnumSet.noneOf(Type.class);
boolean is(final Type type) { return types!=null?types.contains(type):false; }
public static void main(String[] arguments) {
for(Animal a:values()) {
System.out.println(a+" "+a.types);
}
}
}
I think that it is best not to pollute your enum with this sort of categorization. It is best to decouple the categories from the enum so you can add more later without affecting your enum. This follows the seperation of concerns and single responsibility principle for class design.
To do this, just use an EnumSet to hold the instances, viz:
public enum Animal {
DOG,
ELEPHANT,
WHALE,
SHRIMP,
BIRD,
GIRAFFE;
}
public static final EnumSet<Animal> GRAY_ANIMALS = EnumSet.of(ELEPHANT, WHALE);
If you want to add functionality above simple membership, or you want a bit more syntactic sugar extend EnumSet
public class GrayAnimals extends EnumSet<Animal> {
public static final GrayAnimals INSTANCE = new GrayAnimals(ELEPHANT, WHALE);
private GrayAnimals(Animal...animals) {
Collections.addAll(this, animals);
}
public boolean isGray(Animal animal) { return contains(animal); }
// ... other methods
}