I'll explain my issue in a code example. I have this static method called getNewBaby() (that I can not change) it only returns a Animal class. I need someway to convert that animal to Dog. Here's my two failed attempts so far:
public static class Animal
{
public void eat(){}
}
public static class Dog extends Animal
{
public Dog(Animal animal)
{
super = animal; // <-- error 1
}
public void bark(){}
}
.
public static Animal getNewBaby()
{
return new Animal( /* some future parameters */ );
}
public static void main()
{
//Attempt number 1:
Dog puppy1 = (Dog)(getNewBaby()); // <-- error 2
//Attempt number 2:
Dog puppy2 = new Dog(getNewBaby()); // <-- error 3
}
How can I fix this without changing anything in getNewBaby() method ?
What you are trying to do is impossible: you cannot re-initialize super.
However there are alternatives (assuming you cannot modify getNewBaby):
Enclose your down-casting in a try / catch statement and catch a ClassCastException
Use instanceof to check on the actual type, whether it's Animal, Dog, Cat, etc. and base your logic on that
Best choice declare methods in Animal that can be overridden on all child classes, thus de-coupling implementation
Edit
Here are a couple of additional topics - a bit off/broad, but might help you with your design.
Java inheritance and casting
The factory pattern in Java
Java generics
With the new information you have just posted as a comment (which really needs to be emphasized), here is a probably suitable solution for you.
This solution uses composition instead of inheritance. This means your custom class does not extend the original class, but contains an instance of it, and uses it internally.
I used to discourage you from using composition because of the Animal-Dog example, which was conceptually wrong, but here is a different use case, so a different answer ;-)
public class EasySocket {
private Socket socket;
public EasySocket(Socket socket) {
this.socket = socket;
}
/*
* Here are your helper methods that use socket's methods: for instance, use
* socket.getInputStream() instead of simply getInputStream(), since you don't inherit
* from the Socket class anymore.
*/
}
Then when you receive a Socket object:
Socket socket = someServerSocket.accept();
EasySocket easySocket = new EasySocket(socket);
// use easySocket
I can tell you why some things are wrong, but without more information about where you're going, we can't help you reorganize your code, though.
Bad constructor pattern
The following is just wrong with respect to inheritance:
public Dog(Animal animal) {
//...
}
Dog should not need an Animal to be created, because it Is-A Animal, which makes sense here.
Such a construct would be more in accordance to composition, but it wouldn't be appropriate here, and you would need to remove extends Animal on the Dog class.
Affectation of super
The following is not possible in Java because super is just a way of referring to this object as an object from the super class. You can't reaffect this either, because you are currently this object.
super = animal; // <-- error 1
About the cast fail
Casting an Animal to a Dog means that you know the object is indeed a Dog, and you want the compiler to assume it (cast is needed because of Java strong typing).
Here your getNewBaby() method returns an Animal object, not a subclass of it, so won't be able to cast it to Dog (ClassCastException at runtime) because it is simply an Animal (which does not make sense, by the way. Animal should be abstract).
Assuming that I understood your requirement correctly, you can do the following. Instead of trying to assign animal object to super, assign values in animal object to corresponding variables in Dog's super class.
public static class Animal
{
public Animal() {}
public int parameter1 =0;
public Animal(int param1){
this.parameter1 = param1;
}
public void eat(){}
}
public static class Dog extends Animal
{
public Dog(Animal animal) //This is not nice
{
super.parameter1 = animal.parameter1;
}
public void bark(){}
}
.
public static Animal getNewBaby()
{
return new Animal( 4 /*Some integer value for parameter1*/ );
}
public static void main()
{
Dog puppy2 = new Dog(getNewBaby());
}
Related
What's definitely the best way to call a different method of a class according to a different object type in a List?
common example:
public class Dog extends Animals{
...
public void say(){
System.out("i'm a dog");
}
public class Cat extends Animals{
...
public void say(){
System.out("i'm a cat");
}
public class OtherClass {
public void route(){
List<Animals> aList = new ArrayList<>();
a.add(new Dog());
a.add(new Cat());
for(Animals a:aList)
methodOverloaded(a); ---> that's the point <---
}
public methodOverloaded(Dog d){
d.say();
}
public methodOverloaded(Cat c){
c.say();
}
}
Of course, the metaphorical goal is print I'm a dog on the first iteration and I'm a cat on second running methodOverloaded().
I tried
Visitor Pattern
instanceOf()
but I'm looking for better solution.
edit : I stricrtly want to call the overloaded methods of example's OtherClass.
The best way is to define abstract method in Animal and override it in child classes. That's how the polymorphism works.
No need of overloadings.
public abstract class Animal {
public abstract void say();
}
public class Dog extends Animal {
#Override
public void say() {
System.out.println("Bark");
}
}
public class Cat extends Animal {
#Override
public void say() {
System.out.println("Meow");
}
}
Usage:
public class Main() {
public static void main(String[] args) {
List<Animals> aList = new ArrayList<>();
a.add(new Dog());
a.add(new Cat());
for (Animals a : aList)
a.say();
}
}
Output:
Bark
Meow
____UPDATE_1
I would like to add some comments why the overloading these methods is not a good idea.
If you will add the following to your code - it will compile:
public methodOverloaded(Animal a) {
a.say();
}
But it will not work as you're expecting. It will call public methodOverloaded(Animal a) for all the elements of List.
Why does this happen?
For all iterations of the loop, the compile-time type of the parameter is Animal. The runtime type is different in each iteration, but this does not affect the choice of overloading. Because the compile-time type of the parameter is Animal, the only applicable overloading is the third one.
The behavior of this program is counterintuitive because selection among overloaded methods is static, while selection among overridden methods is dynamic.
The correct version of an overridden method is chosen at runtime, based on the runtime type of the object on which the method is invoked.
This can be fixed with:
public methodOverloaded(Animal a) {
if (a instanceof Cat) ? "Meow" :
(a instanceof Dog) ? "Bark" : "Unknown Animal"
}
Of course suggested option with overriding methods demonstrates better approach and more clean code.
Also, a safe, conservative policy is never to export two overloadings with
the same number of parameters, because it can confuse the client of the API. You can always give methods different names instead of overloading them.
But there is the case when at least one corresponding formal parameter in each pair of overloadings has a “radically different” (when it's clearly impossible to cast an instance of either type to the other) type in the two overloadings.
For example, ArrayList has one constructor that takes an int and a second constructor that takes a Collection. It is hard to imagine any confusion over which of these two constructors will be invoked under any circumstances.
You need to define the method in Animal and make it abstract
abstract class Animal {
public abstract void say();
}
this way, you can override this method in each child of Animal, and all you got to do is a.say()
each object will call their respective method.
You can do it like this:
for(Animals a:aList){
if(a instanceof Dog){
methodOverloaded((Dog) a);
}else if(a instanceof Cat){
methodOverloaded((Cat) a);
}
}
But according to the scenario you have described in the question, #J-Alex answer is a good way to go.
I can show you how "Factory Design pattern" is the suitable way here.
Define you main class like:
public abstract class Animal {
public abstract void say();
}
public class Dog extends Animal {
#Override
public void say() {
System.out.println("Bark");
}
}
public class Cat extends Animal {
#Override
public void say() {
System.out.println("Meow");
}
}
public class FactoryClass{
public static Animal getCorrectAnimal(String type){
if("Cat".equalsIgnoreCase(type)) return new Cat();
else if ("Dog".equalsIgnoreCase(type)) return new Dog();
return null;
}
}
public class TestFactoryClass {
public static void main(String[] args) {
Animal an = ComputerFactory.getCorrectAnimal("Cat");
List<Animals> aList = new ArrayList<>();
a.add(FactoryClass.getCorrectAnimal("Dog"));
a.add(FactoryClass.getCorrectAnimal("Cat"));
for (Animals a : aList)
a.say();
}
}
}
Trust me, if you will analyse the level of Abstraction here, it is awesome. The client/consumer never has to know the Dog or Cat class, he/she just has to know the type and a general abstract class Animal. You can even get rid of type here if you use one higher level of abstraction; you can read "Abstract Factory Design" for that. In this way, you expose the least of your class features (like here you exposed Dog and Cat class by using them directly with new in main class). Please upvote if you are satisfied.
For example: Foo ab=new Dog();
Saving object of another type class to reference of another class!
It's not always necessary to do something like Foo foo = new Bar() but it's often recommendable to refer to the interface and not the implementation.
This way you can change your implementation without needing to change other code.
For example if you're doing something with Lists and you use ArrayLists you might do:
ArrayList<Integer> numbers = new ArrayList<>();
//Do stuff with numbers
However you might not care what kind of list it is so you're probably better off with
List<Integer> numbers = new ArrayList<>();
//Do stuff with numbers
Now it doesn't matter what kind of List you've got and maybe you find that you'll get better performance with a LinkedList and you can just use that instead of changing any other code.
I would say that polymorphism is most important when receiving objects by other callers though.
Yes if Foo is an interface then this approach gives you more control on your code. You achieve Polymorphism, Plug-ability, Maintainability and Loose coupling characteristics of java programming language.
Let's say if you are supposed to connect to oracle from your application and written the code like this
OracleDrive driver= new OracleDriver()
driver.connect();
it will solve your problem. But will make your code tightly coupled with OracleDriver. Your application won't compile at all if you remove Oracle related jar from your classpath. And if someone ask you make your app connect to different DBs based on their configuration then you end up with multiple ifs based on your application supported DBs. which is bad practice as per programming standards.
If you all DB drives implements an interface Driver then you can load driver based on configuration without tightly coupling your code to any specific driver class like this
Driver driver = properties.get(db.driver.class)
driver.connect()
Now you see that you need to change you application to connect to MySql you just need to set that class in your configuration file.
Hope you got my point!
It's more useful with method parameters.
class Animal {
public boolean hasHair = true;
public void speak() {}
}
class Dog extends Animal {
public void speak() {
System.out.println("Woof!");
}
}
class Person {
public void shave(Animal a) {
a.hasHair = false;
a.speak();
}
}
class Main {
public static void main(String[] args) {
Person joe = new Person();
Dog fido = new Dog();
joe.shave(fido);
}
}
In this case a Person can shave any Animal, but we pass it a Dog.
Animal fido = new Dog(); would be less useful, because we know fido is a dog, but consider this:
Animal pet;
if(joe.prefersCats)
pet = new Cat();
else
pet = new Dog();
Simple answer, You cannot do that.
More Complicated Answer, You would be able to do that only if 'Dog' is type of 'Foo'.
When will we say Dog is type of 'Foo' is if Dog implements Foo (If an interface) or extends Foo (If another Class or Abstract Class)
Now, coming to advantages of Coding to Interfaces (Technical name of your question) is
1) Java's Polymorphism is based on this (Polymorphism makes runtime change in behaviour possible, Please google polymorphism in java for more information)
2) You are making interfaces independent of implementations by this approach.
hope this answered your question.
This type of declaration is only possible
Foo ab=new Dog();
if Dog class extends class Foo or Foo is an interface which is implemented by Dog class as
class Dog extends Foo { .... }
or
class Dog implements Foo { ... } //Here Foo is an interface
I think so there is no use if you initialize class objects with inherited interface or inherited class as all the base class functions, properties will be available in your derived class object. This type of declaration will come handy if you are initializing multiple objects having same base class with different derived classes.
For Example,
public class MyObject
{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class MyFile extends MyObject
{
private String extension;
public String getExtension() {
return extension;
}
public void setExtension(String extension) {
this.extension = extension;
}
}
public class MyFolder extends MyObject
{
}
If you are initializing
MyObject file = new MyFile();
This is really of no use but it will be useful when we want to initialize
List<MyObject> listOfFilesFolders = new ArrayList<MyObject>();
listOfFilesFolders.add(new MyFile());
listOfFilesFolders.add(new MyFolder());
This 'listOfFilesFolders' can be private variable of another class which keeps list of files/folders present.
Or we want to have function as
private void SomeFunction(MyObject obj)
{
}
which can take all the objects which are derived from base class and perform operation according to base class properties or functions.
See one of my old answers here:
What is the advantage of using interfaces
It's an anecdote about an anecdote that one of my professors once told us.
Long story short, when you get into more complex systems, the reason that you would want this becomes more clear. The ability to separate specification (interface/abstract class and its contract) from implementation (concrete class) is a powerful tool that makes it very easy to write new implementations without having to change code elsewhere in your application. You use the specification in your code, e.g. the specification:
public interface Animal { ... }
Your implementation:
public class Dog implements Animal { ... }
Then in code, you use the specification whenever possible:
Animal a = new Dog();
a.eat(); // All animals eat, so eat() is on the Animal interface
Unless you absolutely need to use the implementation itself:
Dog d = new Dog();
d.bark(); // Other animals don't bark, so we need to have the Dog here
This makes your code cleaner. For example, say I have a method feedAndGroom. If I didn't have an interface, I would need to create a new method for each animal I want to support:
public static void feedAndGroom(Cat c) { ... }
public static void feedAndGroom(Dog d) { ... }
public static void feedAndGroom(Turtle t) { ... }
Each code block might even look exactly the same, depending on the situation. Even worse, what happens when someone discovers a new animal? We'd have to add a new method each time, which would result in a huge number of methods. The solution to all this duplication is to create an interface around the functionality, then have a single method:
public static void feedAndGroom(Animal a) { ... }
This will take anything that implements the Animal interface. All these method calls are legal:
feedAndGroom(new Cat());
feedAndGroom(new Dog());
feedAndGroom(new Turtle());
However, these method calls are legal too:
feedAndGroom(new Hyena());
feedAndGroom(new Lion());
feedAndGroom(new Panther());
We may not want to try and feed and groom these animals, at least not wild ones, so we can add a new interface called DomesticatedAnimal that extends Animal:
public interface `DomesticatedAnimal` extends `Animal` { ... }
And change our method to:
public static void feedAndGroom(DomesticatedAnimal da) { ... }
Then instead of implementing Animal, the Dog, Cat, and Turtle classes will implement DomesticatedAnimal. For example:
public class Dog implements DomesticatedAnimal { ... }
This means that Dog is both a DomesticatedAnimal because it directly implements it, and an Animal by inheritance since DomesticatedAnimal extends Animal. The other animals, Hyena, Lion, and Panther, just implement the Animal interface. This means that our new method won't take just any Animal like our original one, but instead restricts it down to a specific kind of Animal object. Meanwhile, any methods written to use the original Animal interface would still work for all the objects involved.
You can always substitute a reference to a subclass in place of a base class.
In other words, you can always use something more specific in place of something more general—so if you have got a line of code that asks for a Canine, you can send it a reference to a Dog.
So this line of code:
Foo ab=new Dog();
means that you are instantiating a new Dog object, and then creating a
Foo reference called ab and pointing it at that object.
i have a condition where i need to use a fixed Method signature which may accept different type of object. one solution i think is to use a super class and let all as a subclasses. however is there any good elegant design pattern kind of solution where we solve this
also once method gets an object of certain type can we know the type of instance without instanceof check ?
please suggest.
Your question is a little bit vaque, and can be interpreted in two different ways:
Implementing different behavior in one class
Let's assume you have two different classes: Cat and Dog. Then you have a class Animals and want to do something like this:
Cat cat = new Cat();
Dog dog = new Dog();
Animals animals = new Animals();
animals.feed(cat);
animals.feed(dog);
Here feed() executes different code, depending on the parameter type:
public class Animals {
public void feed(Cat cat) {
// ... feed the cat
}
public void feed(Dog dog) {
// ... feed the dog
}
}
This is called method overloading.
Implementing different behavior in different classes
On the other hand, you could define an interface Pet which provides a method, let's say eat():
public interface Pet {
void eat();
}
Then Cat and Dog should implement Pet to get different behavior:
public class Cat implements Pet {
public void eat() {
//...
}
}
public class Dog implements Pet {
public void eat() {
//...
}
}
Then your class Animals would look like this:
public class Animals {
public void feed(Pet pet) {
pet.eat();
}
}
Implementing an interface is a better pattern than inhering a super class. in that way your classes retain their one-inheritance capacity.
regarding the other question about instanceOf, there is rarely a genuine need to determine the actual class of the object. you can always resort to polymorphism. put all methods that you need to invoke on the object in the interface itself. in that way you will never need to know the actual type.
Sorry I'm a beginner just starting out using Java and I've encountered this problem
I have two classes, say they are
class Dog {
}
class Cat {
}
then I created an array that is filled up with either one of those two
Object[][] myAnimal = new Object[4][5];
I want to set a variable equal to a random Object from my array, but I don't know which class it came from. Is there any way to do this?
The ideal solution is to create your own superclass, say Animal which has declares abstract methods. For example, you can do:
abstract class Animal {
public abstract void speak();
}
Then Cat and Dog each provide their own implementations for the abstract method:
class Cat {
public void speak() {
System.out.println("Meow!");
}
}
class Dog {
public void speak() {
System.out.println("Woof!");
}
}
Now you can simply declare your array as
Animal[][] myAnimal = new Animal[4][5];
Place some animals in the array:
myAnimal[0][0] = new Dog();
myAnimal[0][1] = new Cat();
And then tell the animals to speak:
myAnimal[0][0].speak();
myAnimal[0][1].speak();
I have left out the syntax for main() here, but I hope you can put this together yourself. The concepts used here are called "polymorphism". I strongly suggest you study up on it to help you use this crucial OO concept when designing your code.
Well, assuming that your array is filled with instances of one of the two classes, you could do something like:
if(myAnimal[x][x] instanceof Dog) //it is an instance of the Dog class
You really shouldn't do things like this especially as a beginner though. You said that you're trying to select a random dog or cat? The better way would be to keep two separate arrays, one for dogs and one for cats. Then you can select a random element from the two arrays and you'll know what class you're dealing with.
Visitor pattern would be really good approach to consider in such situation. Let say, you are making a game that need to react differently for different object (Cat, Dog, Money, etc). So do this:
Make an interface IAnimal that has following definition:
interface IAnimal {
void visit(IAnimalVisitor visitor, Object param);
}
class Cat implements IAnimal {
void visit(IAnimalVisitor visitor, Object param) {
visitor.visit(this, param);
}
}
class Dog implements IAnimal {
void visit(IAnimalVisitor visitor, Object param) {
visitor.visit(this, param);
}
}
The IAnimalVisitor will contain one visit() method for each animal type defined. So it will be like:
interface IAnimalVisitor {
public void visit(Cat c, Object param);
public void visit(Dog c, Object param);
}
Then you could use put your logic to deal with cat and dog as per you want. For example:
class AnimalFeeder implements IAnimalVisitor {
public void visit(Cat c, Object param) {
c.feed(milk);
c.feed(cat_food);
}
public void visit(Dog d, Object param) {
d.feed(dog_food);
}
}
Then you can use above food feeding class to feed to you IAnimal array like this:
IAnimal[] animals = new IAnimal[] { new Cat(), new Dog(),
new Dog(), new Cat() };
IAnimalVisitor feeder = new AnimalFeeder();
for(IAnimal animal : animals) {
animal.visit(feeder, null);
}
You can achieve full freedom to deal with any level of hierarchy within classes. Just put the visit() for each animal class type within IAnimalVisitor.
I think you have to use reflection api, if you want that class instance , its necessary to check any object at runtime ... i think your question is you don't want to put condition static and how to put condition dynamically for different different animal, today its dog,tiger tomrrow its cow or etc... so plz use refelction api
While coding, I got an interesting doubt about polymorphism and I couldn't understand a solution for this.
public class Animal {
public void getLegs() {
SOP("4 legs");
}
}
public class Kangaroo extends Animal {
public void getLegs() {
SOP("2 legs");
}
public static void main(String[] args) {
Animal a = new Kangaroo(); // without changing this how can I get Animal getLegs
SOP(a.getLegs()); // Important Line
}
}
Now If I want to call the getLegs method of Animal, how do I? Is it possible? Is it still polymorphism?
Yes, it is the most basic form of demonstrating polymorphisim.
Basically you are dealing with an Animal named a. When you call a.getLegs() your code doesn't bind to the implementation of getLegs() in Animal, rather it binds to the lowest sub-class implementation, getLegs() in Kangraoo().
If the Animal has an implementation, it is said to be hidden by the subclass implementation. If Animal has no implementation, then it is not possible to construct stand-alone classes of Animal as they lack implementations for all of the required methods, and under such a circumstance, Animal is said to be an abstract class (one that cannot be constructed directly, but only can be constructed by it's sub classes).
If you really want to call your method for Animal, and you can employ a static method, you can use hiding instead of overriding.
It works as follows: for static methods only, the called method is the one related to the declared type, not the object instance. In other words, it follows the class because the method is a class method, not an instance method.
An example, adapted from this page:
public class Animal {
public static void testClassMethod() {
System.out.println("The class" + " method in Animal.");
}
public void testInstanceMethod() {
System.out.println("The instance " + " method in Animal.");
}
}
public class Kangaroo extends Animal {
public static void testClassMethod() {
System.out.println("The class method" + " in Kangaroo.");
}
public void testInstanceMethod() {
System.out.println("The instance method" + " in Kangaroo.");
}
public static void main(String[] args) {
Kangaroo myRoo = new Kangaroo();
Animal myAnimal = myRoo;
myRoo.testInstanceMethod();
myAnimal.testInstanceMethod();
Kangaroo.testClassMethod();
Animal.testClassMethod();
}
}
The result will be (pay attention to the 3rd and 4th lines, as opposed to the 1st and 2nd):
The instance method in Kangaroo.
The instance method in Kangaroo.
The class method in Kangaroo.
The class method in Animal.
In Java it's not possible to access Animal's implementation. It will always return Kangaroo's version.
(Note in C# it is possible by tagging the overriding method with "new", but it's a fairly specialised use case).
Accessing what appears to be an Animal but getting the behaviour specified by Kangaroo is exactly what polymorphism is - the ability for a child object to be substituted wherever its parent is expected.
In general you wouldn't want to have the calling code know about the inheritance hierarchy because this would tightly couple your code together. If you genuinely need to access Animal's implementation of this method it suggests your design is probably wrong.
The spirit of Polymorphism is to execute different code decided at runtime. To make it more clear, I'll modify your code a bit.
public class Animal {
public void getLegs(){
SOP('4 legs');
}
}
public class Kangaroo extends Animal{
public void getLegs(){
SOP('2 legs');
}
public static void main(String[] args){
Animal a = new Kangaroo(); //without changing this how can I get Animal getLegs
Kangaroo kng= new Kangaroo ();
Animal an = new Animal();
SOP(a.getLegs()); // Kangaroo's version is called
SOP(kng.getLegs()); //Again, Kangaroo's version is called
SOP(an.getLegs()); //Animal version is called
}
}
and Yes, as all say you can't call Animal from your line Animal a = new Kangaroo();..as none will want to do it. Rather he will directly write. Animal a = new Animal();..
So finally it is the object not referance which decides which method will be called
Now If I want to call the getLegs method of Animal, how do I? Is it possible?
If you want to access the overridden method - which contradicts polymorphism - you can use reflection. Get the getLegs method from Animal's class, and then invoke it on your Kangaroo object. However, this is a hack, and not something you'd do in a regular program.
SOP( Animal.class.getMethod("getLegs").invoke(a) );