I implement an Array list in Zoo.java which doesn't inherit any other classes.I will add some objects to this
ArrayList al = new ArrayList();
al.add(new Cat());
al.add(new Dog());
I am unable to write logic which will tell me which type of object is called and using the methods of that class without using Inheritance and Generics.
so here can i use:
for(Animal a:al)
class <?> X = obj.getClass(a);
((X)a).somemethod();
You can create the array list of super class type.
You can do this.
ArrayList<Zoo> arrayList=new ArrayList<Zoo>();
The lesson to learn here is *polymorphism".
the classes Cat and Dog should implement a commont interface that declares methods available for them:
interface Animal {
void eat(SomeOtherInterface food);
void giveSound(BufferedWriter output);
void move();
}
class Cat implements Animal {
#Override public void eat(SomeOtherInterface food){
// consume the food
}
#Override public void giveSound(BufferedWriter output){
output.write("Meaw");
}
#Override public void move(){
// move within the world
}
}
class Dog implements Animal {
#Override public void eat(SomeOtherInterface food){
// consume the food
}
#Override public void giveSound(BufferedWriter output){
output.write("Woof");
}
#Override public void move(){
// move within the world
}
}
Then you give your collecton a generics parameter of the most generic common type providing the methods you want to access:
Collection<Animal> myAnimals = new ArrayList();
myAnimals.add(new Cat());
myAnimals.add(new Dog());
try( BufferedWriter output = new BufferedWriter(new OutputStreamWriter(System.out))){
for(Animal animal : animals)
animal.giveSound(output);
}
Without any instanceOf checks there is no other way to do it; unless your ArrayList::add has a definition that says to take some general Object and that Cat and Dog extends from. But still the only methods you would be able to call would be the methods from that Object, even if Cat or Dog have additional ones. You might see why generics are so handy in these cases...
I did some work on it. To access the methods of objects that are in the array list we can use java.lang.reflect package.
I can first get all the declared methods and then invoke them by using parameters.
so my program will be like:
public class Methodcall{
ArrayList <Object> al = new ArrayList<Object>();
al.add(new Cat());
al.add(new Dog());
for(Object a:al)
{
class ax = a.getClass();
Method[] methods=ax.getdeclaredMethods();
for(Method m:methods)
{
System.out.println(method.getName);
}
}
}
}
after this we can access methods by using other members of reflections.
Thank you all.
Related
I've been trying to write a program where I place animals in an ArrayList of animals and there would be cows, chickens and pigs. The issue that I'm having is that I cant call any method of the subclasses I enter. How could I do this without making an ArrayList of every animal? Thanks in advance!
public abstract class Animal{
protected Boolean feeding = false, walking = false, sleeping = false;
public abstract boolean feed();
public abstract boolean sleep();
public abstract boolean walk();
}
public class Pig extends Animal {
private boolean clean = false;
public Pig() {
super();
}
public boolean cleanUp() {
return clean = true;
}
public boolean feed() {
return feeding = true;
}
public boolean sleep() {
return sleeping = true;
}
public boolean walk() {
return walking = true;
}
}
import java.util.ArrayList;
import java.util.HashMap;
public class Test {
public static void main(String[] args) {
ArrayList<Animal> animals = new ArrayList<Animal>();
Pig pig = new Pig();
animals.add(pig);
// this line wont work
animals.get(0).cleanUp();
}
}
No, you can't do it. You declared your list as a list of type Animal, this type doesn't have cleanUp method.
You could achieve what you want by type-casting, but you need to make sure it's the right class first:
Animal animal = animals.get(0);
if (animal instanceof Pig) {
((Pig) animal).cleanUp();
}
Strictly speaking you don't have to make sure, but believe me: you do.
This is why this code does not compile for Generics
List<? extends Animal> animals = new ArrayList<Pig>(); //COMPILES WITH A WARNING
Pig pig = new Pig();
animals.add(pig); //DOES NOT COMPILE
Which is exactly what you were trying to do. You are putting in a subclass object in a generic list that declares its super class. Java is being proactive because of type erosion. So you have to do explicit casting for this to work. But the design is wrong because you can create a Dog that extends Animal and it will still enter your animals list. So now you have a list full of elements of different objects and due to polymorphism, the methods available during run time is fluid.
I will suggest you create a concrete cleanUp() method on the super class that is general in nature which can be inherited and used as is, or overridden on specific use cases ie if you must have a list of type Animal.
I'm new to Java programming. Please consider the following code snippet.
public class Animal {
public void mate( /*what should I put here?*/ anotherAnimal ) {
}
}
public class Cat extends Animal {
}
public class Dog extends Animal {
}
I want to write the method Animal.mate() in such a way that, when the method is called from a subclass object, the argument fed to the method must be an object of the same subclass, otherwise a compiler error is triggered. For instance:
Cat cat = new Cat();
Dog dog = new Dog();
Animal randomAnimal = new Animal();
Cat trueLove = new Cat();
cat.mate( dog ); // raises a compiler error
cat.mate( randomAnimal ); //compiler error
cat.mate( trueLove ); //passes compiler check
Is what I'm asking possible? I have a vague feeling that it might be possible to do it using generics.
There's no way to make the compiler prevent all bad calls. Even if you parameterize Animal, it would still be possible for something like cat.mate(dog) to be executed at runtime.
If this is required by your business logic, then your best bet is to validate, with something like:
public class Animal {
public final void mate(Animal anotherAnimal ) {
if(!this.getClass().equals(anotherAnimal.getClass())) {
throw new IllegalArgumentException();
}
}
}
If you're doing this mainly to improve compile-time type checking, then you can use generics, knowing the limitations:
class Animal<T extends Animal<T>> {
public final void mate(T anotherAnimal) {
}
}
This will work if your API users use the subclasses rather than the Animal type, and they don't use raw types.
Cat c = new Cat();
c.mate(new Cat());
c.mate(new Dog());//fails
Animal animal = c; //raw type
animal.mate(new Dog()); //only a warning
your problem is about to Polymorphism.
use super class as parameter type in mate method.super class is Animal.
this is the code:
public class Animal {
public void mate(Animal animal) {
System.out.println("Animals mating");
}
#Override
public String toString() {
return "Animal";
}
public class Dog extends Animal {
#Override
public String toString() {
return "Dog";
}
public class Cat extends Animal {
#Override
public void mate(Animal obj) {
System.out.println("cat mating with " + obj );
}
#Override
public String toString() {
return "cat";
}}
and run your code in main method. errors have gone and this is the answer:
cat mating with Dog.
cat mating with Animal.
cat mating with cat.
for better answer instead of saying cat or dog , you can define a name field in Animal class.
Lets say I have a basic animal class
abstract class Animal {
// basic animal code
}
and now I have 2 different animals...
public class Dog extends Animal{
// dog code
}
and
public class Bird extends Animal implements Flyable{
// bird code
#Override
public void fly() {
System.out.println("flap flap");
}
}
Flyable is a simple interface that holds a single method:
public void fly();
if i have a list of animals and i want to loop through it, telling the birds to fly but leaving the dogs alone, how might I achieve this this?
public class Test {
public static List<Animal> animals = new ArrayList<Animal>();
public static void main(String[] args) {
animals.add(new Bird("flop"));
animals.add(new Dog("plop"));
for(Fly f : animals) { // exception here because of mismatch of types
f.flap();
}
}
}
The only option I have found so far is using instanceof to determine whether a class implements the Flyable interface, but a quick google search suggests this is bad for business.
Sources such as:
https://www.quora.com/Is-using-instanceof-in-Java-consider-bad-practice-Any-alternative-to-using-this-keyword
dismiss the use of instanceof as bad design.
I feel like there is an intuitive way of doing this that I have seen before, but cannot find a good solution.
Flyable is a simple interface that holds a single method:
public void fly();
I suppose that was a typo, since the method you call is named flap and not fly.
You can solve the issue by using the instanceof keyword to check if a class is-a superclass.
for(Animal animal : animals) { // loop through all animals
if(animal instanceof Flyable) { // if that animal IS-A Flyable (so it can fly)
((Flyable) animal).flap(); // cast to Flyable and let it fly!
}
}
The only option I have found so far is using instanceof to determine whether a class implements the Flyable interface, but a quick google search suggests this is bad for business
It's not bad at all in my opinion. And it's the only way to accomplish your task.
When you implement the Flyable interface that contains a fly() method declaration in the Animal class, you simply define that each and every subclass of animal has a flying ability.
In my opinion, using instanceof is a bad practice due to the fact that it makes the code pretty confusing: In one hand Dog has a fly() implementation (it indirectly implements the Flyable interface via Animal class), and on the other hand, you don't invoke it when you call fly() on the interface instance.
You have at least 2 ways to prevent Dog from having a flying ability, these are my two favorites:
You can create 2 classes, FlyingAnimal and NonFlyingAnimal which both extend the Animal class while the FlyingAnimal class implements the Flyable interface and the NonFlyingAnimal doesn't.
The Bird will extend the FlyingAnimal class while the Dog will extend the NonFlyingAnimal class.
In this way, you can create a FlyingAnimal list, iterate it, and invoke the fly() method on each and every one of its flying members (the dog isn't one of them).
Use the Strategy Design pattern:
public interface Flyable {
String fly();
}
class ItFlys implements Flyable {
public String fly() {
return "I can fly";
}
}
class CantFly implements Flyable {
public String fly() {
return "I can't fly";
}
}
public class Animal {
private String name;
private double height;
private int weight;
private String favFood;
private double speed;
private String sound;
public Flyable flyingType;
public String tryToFly() {
return flyingType.fly();
}
public void setFlyingAbility(Flyable newFlyType) {
flyingType = newFlyType;
}
}
public class Bird extends Animal{
public Bird() {
super();
flyingType = new ItFlys();
}
}
public class Dog extends Animal{
public Dog() {
super();
flyingType = new CantFly();
}
}
In this way, you set a flying type to each and every subclass of Animal.
When you invoke the fly() method on a Dog class, you will get a "non-flying animal" behavior.
One alternative is to organize your objects such that you don't have to inspect each one in order to determine what to do with it. For example, you might maintain a Kingdom class with various collections of Animal, including a Flyable collection. Iterating over the Flyable collection wouldn't require testing whether each instance was Flyable. If you have other classes that operate on only Flyable objects, they, too, would not have to test each member, leading to cleaner code with less work.
There's a couple of possibilites you can use:
Put fly() in the base class as an abstract method. Make Dog's implementation throw a CannotFlyException, or otherwise implement some "non-flying" behavior. Then iterate over your List<Animal> using
try {
animal.fly();
catch (CannotFlyException() cfe) {
System.out.println("grounded!");
}
Give your Animal() class an abstract method that lists supported operations, then test every member to see if it implements the fly() method:
public abstract class Animal {
private Set<String> behaviors;
public Animal() {
behaviors = new HashSet<String>();
}
public Set<String> getBehaviors() {
return behaviors;
}
}
public class Dog extends Animal {
public Dog() {
super();
behaviors.add("fetch");
}
public String fetch(String fetched) {
return "Dog fetched " + fetched;
}
}
public class Bird extends Animal implements Flyable {
public Dog() {
super();
behaviors.add("fly");
}
#Override
public String fly() {
return "flap flap";
}
}
....
List<Animal> animals = MagicalAnimalListCreator.MakeAnimalList();
for (Animal animal : animals) {
if (animal.getBehaviors().contains("fly")) {
animal.fly();
}
}
You can do it the way you've currently got it, but then try casting every member of your list to Bird and catching a ClassCastException before trying to fly. If the cast succeeds, you've got a Bird and can fly.
This has been asked before here, but the solution is showing a warning saying "Unchecked cast". Is there a safer way to do this. Code is given below.
public abstract class Animal {
.
..
public class Dog extends Animal{
..
public Vector<Animal> myFunc(String[] args) {
// TODO Auto-generated method stub
Vector<Dog> arVector = new Vector<Dog>();
return (Vector<Animal>)(List<?>) arVector;
}
It's not safe because:
Vector<Dog> dogVector = new Vector<Dog>();
Vector<Animal> animalVector = (Vector<Animal>)(List<?>) dogVector;
animalVector.add(new Animal()); // seems to be ok, but...
Dog dog = dogVector.get(0); // Runtime exception - there's Animal, not Dog in your Vector.
There is a reason why compiler won't allow you casting types with different generic types. You can bypass this restriction, but this will probably lead to serious problems in the runtime (*ClassCastException*s).
EDIT:
The problem is that you have to return a Vector with Animals, but you create Vector of Dogs or Cats depending on some conditions. What you can do is:
public Vector<? extends Animal> myFunc(String[] args) {
Vector<Dog> vector = new Vector<Dog>();
// ...
return vector;
}
or:
public Vector<Animal> myFunc(String[] args) {
Vector<Animal> vector = new Vector<Animal>();
vector.add(new Dog());
return vector;
}
Update: My classes are more complex than this, I just am stuck on the ArrayList line
I have the following classes:
class CatList {
List<Cat> cats = new ArrayList<Cat>();
}
and
class DogList {
List<Dog> dogs = new ArrayList<Dog>();
}
Where Cat and dog are both data classes.
but I want to create an abstract class:
abstract class AnimalList {
List<???> animals;
AnimalList(Class animal) {
animals = new ArrayList<???>();
}
}
so that I can inherit my classes
AnimalList CatList = new AnimalList(Cat);
AnimalList DogList = new AnimalList(Dog);
AnimalList CowList = new AnimalList(Cow);
Hopefully that makes more sense. My question is therefore What are the ??? bits?
Using a type parameter might solve your problem - using the same class for different types - without inheritance:
public class AnimalList<T> {
private List<T> list = new ArrayList<T>();
public void add(T animal) {
list.add(animal);
}
// more methods
}
Now you can parametize instances for persons and animals:
AnimalList<Cat> catList = new AnimalList<Cat>();
catList.add(new Cat());
AnimalList<Dog> dogList = new AnimalList<Dog>();
dogList.add(new Dog());
My advice is, to create a base class for Dog and Cat, let's say Animal. This way you spare yourself some time, because you don't have to write the same methods and members in both classes, and it works like this:
public (abstract) class Animal
{
members and functions, that both Cats, and Dogs have...
}
then inherit from Animal like this:
public class Cat extends Animal
{
...
}
From now on you can create an ArrayList like this:
ArrayList<Animal> animals = new ArrayList<Animal>();
animals.add(new Cat());
animals.add(new Dog());
If you want to create an AnimalList anyway, then your best option is Andreas's solution, generics are meant for these kind of situation.
IF you know, how inheritance works, and you already considered building your application like this, then sorry for my post!
As was said, you might want to define a base class Animal for Cat and Dog and then:
class AnimalList<T extends Animal> {
private List<T> animals;
protected AnimalList() {
animals = new ArrayList<T>();
}
}
If you need to pass the Class you might wand to define yje constructor as:
AnimalList(Class<T> type) { … }
If you need to handle some AnimalList for some unknown Animal type you might use:
private AnimalList<? extends Animal> list;