I am currently learning java. I just don't understand the use of interface and I am really confused about it.
These two codes return the same answer, then what is the use of interface here?
interface Jumpable {
abstract int maxDistance();
}
class Animal implements Jumpable {
public int maxDistance() {
return 100;
}
}
public class Forest {
public static void main(String args[]) {
Animal lion = new Animal();
System.out.println(lion.maxDistance());
}
}
class Animal {
public int maxDistance() {
return 100;
}
}
public class Forest {
public static void main(String args[]) {
Animal lion = new Animal();
System.out.println(lion.maxDistance());
}
}
In the state your code is in right now, there is no difference, but that is not what it is about. Further down the line you will need to do things with your animals, without knowing what animals you have or what they can do.
Suppose you want to subclass your animals, into mammals, birds and insects. Some of them can jump, but not others. It will be very ugly code if you create specific classes or attributes for mammals that can jump etc. If you instead create an interface, you have lots of options. You can create a list of animals that can jump, and then tell them to jump, regardless of their type.
Later, you might want to add screaming to your animals. Just add an interface for that.
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();
}
I hope that I explain this clearly. I have an animal (abstract class) that has an eats property, this is meant to be an array of strings representing what each animal can eat. This is how my animal class looks.
public abstract class Animal {
String[] eats;
public Animal (String[] eats) {
this.eats = eats;
}
}
I also have a lion class which extends my animal class. The spec tells me that my lion will eat celery and steak. The constructor in my lion class is as follows (it has a compile error):
public Lion(String[] eats) {
this.eats = steak, celery;
}
I have created these two food objects in a food class, each individual food item has a specified health value and waste value. Here is my food class:
public class Food {
int healthGain;
int wasteGain;
public static void main(String[] args) {
Food steak = new Food();
steak.healthGain = +3;
steak.wasteGain = 4;
//same but for celery instead
}
}
I am really confused as I am meant to have an array of strings for the foods each animal eats, but I have created food objects not strings(the spec does not ask me to do this I just couldnt see another way to do it). Is there a better way to do this? or can I alter my code to make it compile? Either way the food each animal eats must be an array of strings. Thanks in advance.
Your Lion should probably look like this:
class Lion extends Animal{
public Lion() {
super(new String[]{"steak", "celery"});
}
//...
}
Notice that we don't actually need any arguments in constructor since we already know what food Lion eats and it would be bad to ask user to provide this information each time we create Lion object.
BTW if you want to avoid repeating this new String[]{...} code try changing your Animal constructor to use varargs
public Animal (String... eats) {
// ^^^
this.eats = eats;
}
This will still allow you to see eats as array of Strings (String[]) so you can assign it to this.eats without any problem, but now Lion constructor can look like:
public Lion() {
super("steak", "celery");
}
Here is a short sample on how to proceed:
public static void main(String args[]) {
// Initialize this array with food types
String[] foods = new String[] {"celery", "meat"};
Lion lion = new Lion(foods); // Pass in the foods as an argument
}
public Lion(String[] eats) {
super(eats); // Call the overloaded Animal constructor
}
This is what you should do:
class Lion extends Animal
{
public Lion(String[] eats) {
super(eats); //invoke superclass constructor
}
}
Since eats is not private, it will be inherited. Also remember to invoke superclass's constructor, else you will get a compilation error.
You don't hard code what Lion eats within Lion class. You do it in the main():
//In the main method
String[] eats = {"celery", "steak"};
new Lion(eats);
If I had an array of Birds that is filled during run-time, how can I access member methods specific to child classes?
class Bird
{
public Bird() {}
public void fly(int x) {
System.out.println("Flew "+x+" meters");
}
}
class DumbBird extends Bird
{
public DumbBird() {super();}
public void fly(int x) {
x-=5; //we're dumb
System.out.println("Flew "+x+" meters");
}
public void sing() {
System.out.println("La la la!");
}
}
public static void main(String[] args)
{
Bird[] cage = new Bird[10];
cage[0] = new Bird();
cage[1] = new Dumbbird();
cage[2] = new Sleepybird();
//.... more bird types
cage[1].sing(); //is inaccessable because it is of type Bird not DumbBird!
}
Is there a good way to be able to have a an array of generic types while being able to access member functions specific to a child class? I would like to not have to edit the Bird class.
In theory, yes. Items put in arrays are reifiable, so you could determine which type you're looking at and cast the particular object to it's actual type. This isn't a very clean solution, though, so I wouldn't recommend it.
You may consider having an abstract class or interface representing bird that has methods most birds would support, along with a check method canSing() or canFly(). Birds that don't support this such as flightless birds can throw an UnsupportedOperationException if you try to call a method the bird doesn't support, but there is no easy way to generically reference all of the birds and know about all of the different methods each sub-type of bird can have.
Just to remove my answer from the comments.
Switch to using lists instead of arrays and when you pull your specific bird out, you will need to cast it to the correct type of "Bird", see the below code example:
import java.util.ArrayList;
class Bird
{
public void fly(int x) {
System.out.println("Flew "+x+" meters");
}
}
class DumbBird extends Bird
{
public void fly(int x) {
x-=5; //we're dumb
System.out.println("Flew "+x+" meters");
}
public void sing() {
System.out.println("La la la!");
}
}
class Test {
public static void main(String[] args) {
ArrayList<Bird> cage = new ArrayList<Bird>();
cage.add(new Bird());
cage.add(new DumbBird());
cage.add(new Bird());
cage.add(new DumbBird());
cage.add(new SleepyBird());
((DumbBird) cage.get(1)).sing();
}
}
This may sound like a noob question, But I was searching what are interfaces and I found this example.
Whats the difference between this
interface InterfaceA
{
void interfaceMethodA();
}
public class ImplementingClassA
implements InterfaceA
{
public void interfaceMethodA()
{
System.out.println("interfaceA, interfaceMethodA, implementation A");
}
}
Other than this.
public class ImplementingClassA
{
public void interfaceMethodA()
{
System.out.println("interfaceA, interfaceMethodA, implementation A");
}
}
I did not find any difference, if so what are used the interfaces for?
When you have multiple classes that need to do the same actions but the actions will each be slightly different or even very different then you need an interface. For example lets say you want certain foods to be edible. If you inherit an eating method all the foods will have to be eaten the exact same way. That is why you use an interface like so...
interface Iedible {
public void eat();
}
So by definition if something implements Iedible I know you can eat it but the behavior of how to eat it might be different. For example soup you would have to sip where a cake you would have to bite.
In this case we have a cookie and we all know there is only 5 bites in a cookie.
public static class Cookie implements Iedible {
int bites = 5;
public void eat() {
if (bites > 0) System.out.println("*bites cookie* you have only " + --bites + " bites left");
else System.out.println("no more cookie left :(");
}
}
Now we have vegetables and we know you never run out of vegetables because of how tiny the bites you take are.
public static class Vegetable implements Iedible {
public void eat() {
System.out.println("Everyone knows vegetables are not edible but you try to eat it anyway *takes a microscopic bite*");
}
}
So we see both the Cookie and the Vegetable both are able to eat() but the implementation of those eat() actions are fundamentally different.
Now here is where interfaces really shine. Now I want a class called dinner which can accept ANY object which can be eaten and then I want a method that will allow me to TRY everything on the dinner table.
public static class Dinner {
ArrayList<Iedible> foods = new ArrayList<Iedible>();
public Dinner(Iedible... food) {
for (int i = food.length - 1; i >= 0; i--)
foods.add(food[i]);
}
public void tryEverything() {
for (int i = foods.size() - 1; i >= 0; i--)
foods.get(i).eat();
}
}
In your example above where you just gave both classes the same method you will be unable to make this dinner class without interfaces because just because both classes have the same method the compiler doesn't know that unless you implement an interface.
And then of course here is our interface in action...
public static void main(String[] args) {
Cookie cookie = new Cookie();
Vegetable vegetable = new Vegetable();
Dinner dinner = new Dinner(cookie, vegetable);
dinner.tryEverything();
}
I hope this helps you gain some practical ideas for interfaces and understand that the example above I just gave will be impossible to replicate without interfaces.
It's part of a contract in the first instance, consider another implementation of the interface -
public class ImplementingClassB
implements InterfaceA
{
public void interfaceMethodA()
{
System.out.println("interfaceA, interfaceMethodA, implementation B");
}
}
now you could use
InterfaceA foo = new ImplementingClassA();
InterfaceA bar = new ImplementingClassB();
foo.interfaceMethodA();
// and/or
bar.interfaceMethodA();
Hi I'm wondering if there is a simple solution to my problem,
I have an ArrayList:
ArrayList <Animal> animalList = new ArrayList<Animal>();
/* I add some objects from subclasses of Animal */
animalList.add(new Reptile());
animalList.add(new Bird());
animalList.add(new Amphibian());
They all implement a method move() - The Bird flies when move() is called.
I know I can access common methods and properties of the super class by using this
public void feed(Integer animalIndex) {
Animal aAnimal = (Animal) this.animalList.get(animalIndex);
aAnimal.eat();
}
That's fine - but now I would like to access the move() method the subclass Bird has.
I could do this by casting the Animal as a Bird:
Bird aBird = (Bird) this.animalList.get(animalIndex);
aBird.move();
In my situation I don't want to do this, as it will mean I have 3 different sets of the above code one for each subtype of Animal.
It seems a bit redundant, is there a better way?
There really isn't a nice way to do this from the superclass, since the behavior of each subclass will be different.
To ensure that you're actually calling the appropriate move method, change Animal from a superclass to an interface. Then when you call the move method, you'll be able to ensure that you're calling the appropriate move method for the object you want.
If you're looking to preserve common fields, then you can define an abstract class AnimalBase, and require all animals to build off of that, but each implementation will need to implement the Animal interface.
Example:
public abstract class AnimalBase {
private String name;
private int age;
private boolean gender;
// getters and setters for the above are good to have here
}
public interface Animal {
public void move();
public void eat();
public void sleep();
}
// The below won't compile because the contract for the interface changed.
// You'll have to implement eat and sleep for each object.
public class Reptiles extends AnimalBase implements Animal {
public void move() {
System.out.println("Slither!");
}
}
public class Birds extends AnimalBase implements Animal {
public void move() {
System.out.println("Flap flap!");
}
}
public class Amphibians extends AnimalBase implements Animal {
public void move() {
System.out.println("Some sort of moving sound...");
}
}
// in some method, you'll be calling the below
List<Animal> animalList = new ArrayList<>();
animalList.add(new Reptiles());
animalList.add(new Amphibians());
animalList.add(new Birds());
// call your method without fear of it being generic
for(Animal a : animalList) {
a.move();
}
You dont need to do any casting. The overridden method should get called [simple polymorphism]
Animal aAnimal== this.animalList.get(animalIndex);
aAnimal.move();
Above code should call bird method if object is of bird, isn't it?
And casting is not a solution , how will you decide which object to cast? You will have to use instanceOf.
In your case,the following could work,but time complexity is O(n):
public void moveBird(){
for(Animal aminal:animalList){
if(animal instanceof Bird){
aninmal.move();
}
}
}
Bird getMyBird(Integer aniInteger) {
Bird b = new Bird();
//Do somthig with bird object...
return b;
//get your modifeid bird object
}
Bird myBird = animalList.get(animalIndex);
myBird.move();