Inheritance in Java, how to design clasess without own attributes - java

I am not sure how to represent a model in Java which include inheritance. I have three classes which inherit from a super class, but one of them doesn't have different attributes neither methods than super class, for example:
public class Animal{
public int a;
public int b;
public int c;
}
public class Cat extends Animal (){
public int d;
public int e;
}
public class Dog extends Animal {
public int f;
public int g;
}
public class Cow extends Animal {
//it doesn't have different attributes or methods than Animal
}
(Attributes and classes above are only examples)
How should I design that? Is it correct to have a class wich only extends from a super class without having its own attributes? or should I omit Cow class and instantiate it from Animal? Thank you!

Animal class is better to be an abstract class with common methods that all animals share.
then you can create a class Cow extend the abstract class so that you can call those common method( e.g. eat and drink and specify methods for cow such as moo()

It is ok to create a Cow class that extends Animal even though it doesn't add any attributes. A Cow is still a type of animal even if it doesn't add any behavior or data to the Animal class that is specific to being a Cow.

I think that you should create a new class representing a Cow object just the same. Consider a few months from now you would like to add some new behaviour... without the Cow class you would need to rewrite certain sections of your code... sections you most likely had already tested.

It's ok to create a Cow class as #Chris said, plus imagine if you had a method to feed the animals you method would look something like this:
public void feedAnimal(Animal animal);
now if you wouldn't extend cow to class Animal you would have to create a second method to feed the cow:
public void feedCow(Cow cow);
even tough it's an animal

If you have other Animals other than Cat, Dog and Cow and you use objects for those Animals by instantiating the Animal class then there is no point for another Cow class that does not bring anything new (not new fields, no new methods, no overridden methods).
On the other hand you only have Animals of type Cat, Dog and Cow then you should make your Animal class an abstract one (or an interface for greater flexibility).

IMHO if your Cow class is identical to Animal there's something wrong in your design.
I mean, instead of extending an Animal class, maybe you need a BasicAnimal class and several extending classes only when you actually need to add features.
Or an alternative could be to transform yor Animal class to an interface (or an abstract class) and implement/extend it.
In the abstract class you should implement only common methods. But if you find that the behavior of Cow is the same of Animal could be better to go the BasicAnimal way...

Three reasons why you should not implement "cow" in class animal:
The word animal is itself an abstraction (the class should be abstract, impossible to make a new).
When you define a class, you define a type (cow is a concrete type even without no attributes or method). You can also use "instance of" to disambiguate if necessary
Last and most important, when you use inheritance, you should always comply with the principle of substitution (all elements that refer to "Animal", should work replacing "Animal" by "cat", "dog" or "Cow")

Related

How to make a type part of another type? (Java)

This question isn't worded the best, but essentially I created some classes that can be used as types called Dog, Cat, Whale, etc. I also made another class that could take in a pet. How would I make classes like dog, cat, etc. belong to the pet type?
What you're looking for is called inheritance. In Java, you use the extends keyword in the class definition to make one class extend another.
For example:
public class Dog extends Pet { ...

Polymorphism in Java error:cannot find Symbol

I've just started learning object oriented programming from the book head first java.It said that polymorphism enables me to create an array of the superclass type and then have all the subclasses as the array elements.But when I tried writing code using the same principles it ran into error saying
error: cannot find symbol
I made the classes the superclass was animal and the dog class extended the animal class having a fetch method of its own, but when I referenced the dog variable as animal it did not work here is the code
The Animal class:
public class animal{
String family;
String name;
public void eat() {
System.out.println("Ghap Ghap");
}
public void roam() {
System.out.println("paw paw");
}
}
The dog class:
public class dog extends animal {
public void fetch() {
System.out.println("Auoooooooo");
}
}
The Tester class:
public class tester {
public static void main(String args[]){
animal doggie = new dog();
doggie.fetch();
doggie.eat();
doggie.roam();
}
}
The error:
tester.java:4: error: cannot find symbol
doggie.fetch();
^
symbol: method fetch()
location: variable doggie of type animal
1 error
Edit: Last time I asked this question I went home thinking the object doggie is of the type animal and it has no idea of about the fetch() function that has been declared in the dog class. But adding the line
System.out.println(doggie.getClass().getName());
Gives dog as the type of the class, if dog is indeed the type of the class, shouldn't it have the knowledge of the method declared within it
?
When using polymorphism, if you create an instance of the subclass and store its reference in a variable of superclass type, you can only call those methods on the newly created instance which are present in the super class.
In your code, you created an instance of dog class and stored its reference in doggie which is of type animal (super class of dog), In such case, you can't call any method on dog class instance that isn't available in animal class.
fetch method is not defined in the animal class hence you get the error.
Solution
Either define the fetch method in the animal class
OR
change
animal doggie = new dog();
to
dog doggie = new dog();
Since the fetch() method doesn't exist in animal, its throwing the error.
You can define a fetch method in animal and override it in dog class.
You are referencing doggie.fetch() but this is not a method defined in animal.
Since you are using your doggie object as an animal you can not use this method.
If you would like to use the method, you can do something like an instance check:
if(doggie instanceOf dog){
((dog)doggie).fetch();
}
If you really want to understand the depth of this concept, you should understand the Liskov Substitution Principle, which, in a brief, is described as follows:
In a computer program, if S is a subtype of T, then objects of type T may be replaced with objects of type S (i.e., an object of type T may be substituted with any object of a subtype S) without altering any of the desirable properties of the program.
Central idea behind this concept is to NOT break the contract "signed" with the parent type (that is, extending a class, or implementing an interface).
If you were able to invoke any method, available in your subtype, on the reference stored in its parent type, disregarding the contract between your subtype and its super type(s), you may have an unintended malfunction - runtime exceptions, to be more precise.
Last but not least: Please follow the Java naming conventions and name your classes with the Pascal Case convention. This is very important.

What happens when an abstract class implements an interface in Java

I am new to Java, coming from a C++ background and I try to understand the concept of interface and abstract class implementing an interface. What exactly happens when an abstract class implements an interface? Does this work like inheritance, i.e. all interface methods belong also to the abtract class eventhough they are not implemented in it? Or will only the implemented methods belong to the abstract class? So is there any difference between implements and extends, except that one is used to implement interfaces and the other one is used for inheritance?
You can imagine an abstract class as an unfinished class. It's like a template for actual real classes. Interfaces are mainly used to describe properties, like CanWalk, IsCloseable, HasAName and so on.
There is no big difference between both concepts from the language perspective, other than that you can only extend from one class but are allowed to implement multiple interfaces.
In the end of the inheritance chain you will always have non-abstract concrete classes. Which is obvious, you can't use unfinished classes in the end, you need to finish them. That's why
Animal animal = new Animal();
does not work if Animal is abstract. We need to create instances of finished classes, like a Dog who extends from Animal.
And at that point, where you have a finished (non-abstract) class, all abstract methods need to be implemented. It doesn't matter from where those methods come from, abstract classes or interfaces, they need to be implemented.
So if you have an abstract class and implement an interface with it, you have two options for the interface methods. You either
implement them in the abstract class or
you leave them abstract, but then some of your more concrete children need to implement it.
Example
Let's suppose we have an interface like
public interface CanMakeNoise {
void makeNoise();
}
and the abstract class
public abstract class Animal implements CanMakeNoise {
public abstract void jump();
...
}
together with a concrete extending class
public class Dog extends Animal {
...
}
Since Dog is not abstract, all methods need to be implemented. That is, we need implementations for jump and makeNoise. For the makeNoise method we have two options, either Animal implements it or it leaves it abstract, then Dog needs to implement it:
// Variant 1
public abstract class Animal implements CanMakeNoise {
public abstract void jump();
#Override
public void makeNoise() {
System.out.println("hello, what's up");
}
}
or
// Variant 2
public abstract class Animal implements CanMakeNoise {
public abstract void jump();
}
public class Dog extends Animal {
#Override
public void makeNoise() {
System.out.println("Wuff wuff");
}
}
And of course Dog needs to implement jump:
public class Dog extends Animal {
#Override
public void jump() {
System.out.println("Boing");
}
...
}
In this case it's probably better to leave the implementation of makeNoise up to more concrete classes since Animal has no clue how a specific animal will sound like.
Extending the example, if you have even more concrete classes like a Chihuahua extends Dog, you could implement the makeNoise in Dog since all dogs do "Wuff, wuff".
A method belongs to implementing class of course. I won't say that it doesn't matter where it comes from because of polymorphism. In Java you don't have multi-inheritance but you can implement multiple interfaces, so this is giving you more options about the hierarchy.
In Java, a class can only inherit from one class, but can implements multiple interfaces.
An abstract class is very similar to an interface. The main difference is that an abstract class can define some function already, an interface can’t (note that this changed in Java9+).
Which one to use? Well it really depends on your structure but the javadoc defines some exemple.
If you are worried about the usage of the interface then it will be used for callbacks as Java don't support function pointers.

Can a subclass also be a superclass?

Can a subclass also be a superclass of another subclass in Java? Perhaps this is not the best example, but consider the following classes:
public class Animal { }
public class Dog extends Animal { }
public class Cat extends Animal { }
public class Siamese extends Cat { }
public class JackRussel extends Dog { }
Does inheritance allow for this sort of behaviour?
Given that JackRussels would require the methods and properties of both an Animal and a Dog, and Siamese's would require the methods and properties of both Animal and Cat.
If not, is there a generalised approach I could take to achieve this sort of behaviour?
Cheers
Yes, that behavior is exactly what is expected when using inheritance in Java.
Here's some quick reading that you may find usefull: http://www.homeandlearn.co.uk/java/java_inheritance.html
Your JackRussel object will inherit all fields and methods from it's Animal and Dog super-classes that are:
not declared private;
are not overridden (in which case will get only have access to the overridden one);
are not shadowed (in which case will get only have access to the shadowed one);
Here's another quick link on shadowing and overriding in Java:
http://docstore.mik.ua/orelly/java-ent/jnut/ch03_04.htm
Having those point in mind, you can easily design inheritance tree that can propagate parent’s behavior and state to all of its children.
Thanks.
Of course this is possible. But saying that the Siamese would require methods and fields from both superclasses is a bit wrong. When cat extends animal it gets all of the fields and methods of animal (if you do not override them). Then, when Siamese extends that cat class, it will automatically get the whole Cat class, including the things that are from the Animal class, regardless of whether they are overriden or not.
In short terms, this is possible.

Java- What can be done by interfaces that can not be done by abstract class?

I know the difference between "interface" and "abstract class". But could you provide me the single example which can be built through the "interface" but not through the "abstract class" leaving the example of "multiple inheritance"?
A simple example is with objects that represent the same entity but have different bevaviour. Consider for instance the birds. Some birds can fly and some can't. It would be wrong to define an abstract class Bird which forces all it's subclasses to implement a fly method.
So in such a case it's ok to define methods as eat() or sleep() as abstract in the abstract class Bird but not fly() since not all birds can fly.
Generally you would define an interface called for instace Flyable which would contain the definition of the fly() method, which would have to be overriden by classes implementing the interface.
In the end you would end up with something like:
public abstract class Bird{
public abstract void eat();
public abstract void sleep();
}
public interface Flyable{
void fly();
}
public class Eagle extends Bird implements Flyable{
.... has to implement eat(), sleep() and fly()
}
public class Ostrich extends Bird{
... has to implement only eat() and sleep() since ostrich can't fly
}
100% percentage abstraction is called Interface.
List is a interface. It jus jas method definition.
Abstract Class : It has some method implementation.
AbstractList is a abstract class . It has method implementation.
Comparable interface in java.lang.Comparable can never be implemented as a class (i.e Abstract class)
This is because the compareTo method depends completely upon the class which imnplements it. And it is required that for all object comparisons, they should have implemented this method (The objects that are being compared)
Note: Comparable class is used to compare 2 objects for equality
Whereas AbstractStringBuilder is better written as an abstract class is extended by both StringBuilder as well as StringBuffer.
This way the common functionalities (like charAt, expandCapacity, indexOf )in both the classes can be put in this abstract class..This way code can be reused which cannot be in case of an interface

Categories

Resources