There is an abstract class containing non-abstract methods only. Now I create another class which extends abstract class. For ex :
abstract class Parent{
void No(){
System.out.println("abcd");
}
}
class Child extends Parent {
}
Instead of abstract class, I could have create another class. What is use of making this above class as an Abstract ?
I guess what you want to know is if in this case it make any difference not to make abstract:
No it doesn't: as long as you do not have abstract methods, you can use abstract or non-abstract classes (even if abstract makes no sense in this case). But if you've one abstract method, you class needs to be marked as abstract.
an abstract class without any abstract methods sometimes is a design decision. for example, a regular expression can be implemented like this:
public abstract class Regex {
private Regex(String pattern) { /* do something */ }
private static class ConcreteRegex {
private ConcreteRegex(String pattern) {
super(pattern);
}
}
private static final int MAX_CACHE_SIZE = 100;
private static Object cacheLock = new Object();
private static Queue<String> patternq = new LinkedList<>();
private static Map<String, Regex> cache = new HashMap<>();
private static Regex checkCache(String pattern) {
synchronized(cacheLock) {
return cache.get(pattern);
}
}
private static void insertCache(String pattern, Regex regex) {
synchronized(cacheLock) {
patternq.offer(pattern);
cache.put(pattern, regex);
while(patternq.size() >= MAX_CACHE_SIZE) {
String key = patternq.poll();
cache.remove(key);
}
}
}
public static Regex compile(String pattern) {
Regex result = checkCache(pattern);
if (result == null) {
Regex compiled = new ConcreteRegex(pattern);
insertCache(pattern, compiled);
return compiled;
}
return result;
}
public static Matcher match(String pattern, String str) {
Regex result = compile(pattern);
return result.matches(str);
}
// define find, findall, and so on like this
}
so what's the point to do all these work? well, sometimes it would be quite handy to have these methods to shorten the program, while it may have a chance to increase the performance of the program. by doing this, we need to prevent user to call the constructor directly. but why not have these caching management inside of the constructor?
well, this is not recommended(it will compile though), since you are leaking the instance out in the middle of instantiation, such that there is a chance to reference the partially instantiated object, which may generally be considered as a dangerous behavior.
of course, there are other cases where you decide to have such "weird" abstract classes, which are too many to enumerate.
It's true that if an abstract class has no abstract methods, then there's nothing that forcibly prevents would-be clients from creating a trivial child class and instantiating it; but keep in mind that we write code to be read and understood, not just by the compiler, but by other programmers (including our future selves). We cannot forcibly prevent those programmers from messing up; but we can write code that helps them do the right thing.
So the question is — what is a situation where a class has no abstract methods, but where it nonetheless doesn't make sense to instantiate it directly?
There are a few possibilities that come to mind, but I'll just mention one.
Consider an interface like java.util.List, where many of the methods are convenience methods that can be defined in terms of others. In particular, the methods that use iterators can be defined in terms of the methods that use indices, and vice versa.
One could easily imagine an abstract List implementation that defines all of these methods, but in terms of each other. You could then easily implement List by subclassing this implementation and overriding either an iterator-y method or an index-y method.
(As it happens, this is not the approach the JDK takes. The JDK instead offers two abstract implementations, java.util.AbstractList and java.util.AbstractSequentialList, each of which has some abstract methods for the subclass to fill in. I think the JDK's approach is superior, because it makes it clearer what you are supposed to do, and generates a compile-error where the combined-abstract-class approach generates a StackOverflowError at runtime. But I would not fault the developer who, with a surfeit of DRY, took the combined-abstract-class approach.)
One advantage I see is that you prevent people instantiate it.
For example you want to make a system of vehicle. In the parent abstract class, there is only one method run(){}, well, not abstract. You want to instantiate it as VW, TOYOTA OR Ford, but not a non-specified brand vehicle. You inherent vehicle class as non abstract class VW, Toyota or Ford. but you couldn't start with vehicle, cuz it's more like a "type", not something you want to build.
Related
let me first explain what i want to say actually
Suppose a class Sub inheriting the class Super.
now we can excess all no private members of class Super within class Sub. now Suppose the case
class Super{
private int id;
public int getId()
{
return id;
}
}
class Sub extends Super {
public static void main(String args[]){
Sub sub = new Sub();
System.out.println(sub.getId());
}
}
I know that creating Sub class object will call Super class constructor too.
But the job of constructor is to initialize the fields only -- not to allocate the memory to the object.
Moreover in case of abstract class where the initialization is not allowed we can still use the instance variable of abstract class.
The memory to instance variable will be assigned at time of instance creation only.
Than how can we use the instance fields without even creating the instance.
Doesn't it violets the oops concept..??
Please help over this. And thanks in advance.
I think you're confused about what happens when you use the extends keyword. What that keyword means is that a Sub is a more-specific kind of Super. By the Liskov Substitution Principle, all of the properties of Super must hold for Sub as well. That means that all of Super's private members (methods and properties) are present in an instance of Sub. It's just that for organizational reasons, the developer of Super decided that they didn't want any derived classes messing around with it directly.
Now, how does this relate to memory allocation? In the case of Java, you are correct that the constructor does not allocate memory. It just initializes the fields. The memory allocation is handled by the runtime, and it allocates enough for the whole picture. Remember, a Sub is a Super and then some. So it allocates enough memory to hold everything from the entire inheritance chain all the way back up through java.lang.Object.
abstract classes can, in fact be initialized, or even force their derived classes to initialize their members. For example:
public abstract class Super {
private int id;
public Super(int id) {
this.id = id;
}
public int getId() { return this.id; }
}
public class Sub extends Super {
public Sub() {
super(5); // failure to call this constructor is a compiler error
}
}
Now, because Sub can't see Super's private id field, it's free to declare a new one of its own. This does not override Super's field. Any of Super's methods that use that field will still use the one from Super. This could be a little confusing, so the best advice is don't think of it that way. Generally, you'll want to override methods not fields.
I totally agree with the answer of Ian. Totally. Regarding the title of your question,
Does inheritance violates the basic law of oops..?
the answer is it depends. There is a kind of inheritance that violates encapsulation principle: implementation inheritance.
You're using implementation inheritance every time you inherit (through extends primitive) from a class that is not marked as abstract. In that case, to know how to implement your subclass, you need to know the implementation (a.k.a. the code) of methods of the base class. When you override a method, you have to know exactly which is the behavior of that method in the base class. This kind of code reuse is often referred to as white-box reuse.
Quoting the GoF's book, Design Pattern:
Parent classes often define at least part of their subclasses' physical representation. Because inheritance exposes a subclass to details of its parent's implementation, it's often said that "inheritance breaks encapsulation".
So, to reduce implementation dependencies, you have to follow one of the principles of reusable object-oriented design, which is:
Program to an interface, not an implementation
inheritance only concern about what and how is accomplished, not what is promised. If you violate the promises of the base class, what will happen? is there any guarantee that makes you sure it's compatible? -even your compiler will not understand this mistake and you will face a bug in your codes. Such as:
class DoubleEndedQueue {
void insertFront(Node node){
// ...
// insert node infornt of queue
}
void insertEnd(Node node){
// ...
// insert a node at the end of queue
}
void deleteFront(Node node){
// ...
// delete the node infront of queue
}
void deleteEnd(Node node){
// ...
// delete the node at the end of queue
}
}
class Stack extends DoubleEndedQueue {
// ...
}
if the class wants to use inheritance with aim of code reuse, It may inherit a behavior that violates its principal, such as insertFront. Let's also see another code example:
public class DataHashSet extends HashSet {
private int addCount = 0;
public function DataHashSet(Collection collection) {
super(collection);
}
public function DataHashSet(int initCapacity, float loadFactor) {
super(initCapacity, loadFactor);
}
public boolean function add(Object object) {
addCount++;
return super.add(object);
}
public boolean function addAll(Collection collection) {
addCount += collection.size();
return super.addAll(collection);
}
public int function getAddCount(Object object) {
return addCount;
}
}
I just reimplement HashSet with DataHashSet class in order to keep track of inserts. In fact, DataHashSet inherit and is a subtype of HashSet. we can instead of HashSet just pass DataHashSet(in java is possible). Also, I do override some of the methods of the base class. Is this legitimate from Liskov substitution principle? As I do not make any changes in the behavior of base class just add a track to insert actions, It seems perfectly legitimate. But, I will argue this is obviously a risky inheritance and a buggy code. First, we should see what exactly add method do. add one unit to related property and call parent class method. There is a problem with that called yo-yo. Look at addAll method, first, it adds collection size to related property then call addAll in the parent, but what exactly parent addAll do? It will call add method several times(loop over the collection), which add will be called? the add in the current class, so, the size of count will be added twice. once when you call addAll and second when parent class will call add method in the child class, that's why we call it yo-yo problem. And another example, imagine:
class A {
void foo(){
...
this.bar();
...
}
void bar(){
...
}
}
class B extends A {
//override bar
void bar(){
...
}
}
class C {
void bazz(){
B b = new B();
// which bar would be called?
B.foo();
}
}
As you see in bazz method which bar will be called? the second one the bar in class B will be called. but, what is the problem here? the problem is foo method in class A will not know anything about the override of bar method in class B, Then your invariants may be violated. because foo may expect the only behavior of bar method that is in own class, not something is overridden. This problem is called fragile base-class problem.
Can have an abstract class implementing all of its methods-- with no abstract methods in it.
Eg.:
public abstract class someClass {
int a;
public someClass (int a) { this.a = a; }
public void m1 () { /* do something */ }
private void m2 () { /* do something else */ }
}
What's the advantage, if any, of having such an abstract class compared to having the same class as a concrete one instead?
One i can think of is that, when i declare it as abstract, it won't be instantiated.
however, i can have the same effect by making it concrete and its constructor(s) private.
TIA.
//==================
EDIT: One other use I can think of:
it may be extending another abstract class or implementing an interface without implementing that class's abstract methods-- although it is implementing all methods of its own. for whatever it' worth.
It has a conceptual meaning: this class has a behaviour which makes no sense on its own.
Granted, it's difficult to imagine such a scenario without well-defined extension points (i.e. abstract methods), but occasionally it will be a reasonably accurate model of your problem.
You can have something like this:
public abstract class ObjectWithId {
private final String id;
public ObjectWithId( String id ) {
this.id = id;
}
public final String getId() {
return id;
}
}
And then you can extend it to declare different types of objects that have ids. Here you have a fully specified and implemented behaviour but no restriction on any other behaviours subclasses may exhibit.
Note though that a much neater way to model the same thing is to use composition instead of inheritance.
public final class ObjectWithId<T> {
private final String id;
private final T ob;
public ObjectWithId( String id, T ob ) {
this.id = id;
this.ob = ob;
}
public String getId() {
return id;
}
public T getObject() {
return ob;
}
}
But before generics were introduced (up to Java version 1.4), this wouldn't have been as elegant and obviously better than the abstract class solution because you'd have had to trade in type safety.
you can declare to implement an interface and don't provide implementation and then each child implicitly gets interface extended
you prevent to create instance of this class
you in future provide common implementation to all children
As you pointed out, you can prevent the class from being instantiated by making it's constructor private. Othere than that, there is no benefit whatsoever. This is probably supported just to provide language completeness.
We generally use Abstraction concept with inheritance
Consider using abstract classes if any of these statements apply to
your situation:
You want to share code among several closely related classes.
To answer your question,
Why declare a class with concrete methods Abstract?
One possible reason is to support inheritance without actually creating objects
Assume you have two classes one Abstract and other Concrete
Abstract class : AbsClass
abstract class AbsClass {
int a = 5;
//Constructor
public AbsClass() {
System.out.println(a);
}
void methodA() {
System.out.println(a + 10);
}
}
and
Concrete class : ConcreteClass
class ConcreteClass {
int a = 10;
//Made the constructor Private to prevent from creating objects of this class
private ConcreteClass() {
System.out.println(a);
}
void methodA() {
System.out.println(a + 10);
}
}
The above two classes should function similarly (?) Until you try to Subclass them
class AbsImplementer extends AbsClass {
//Works fine
}
class ConcImplementer extends ConcreteClass {
//Compilation Error Implicit super constructor ConcreteClass() is not visible
}
The practical difference is that you can't create an instance of it. You would have to subclass it and create an instance of the subclass.
As to WHY you would want to do this, in practice ... I'm hard pressed to think of a good reason. You could say that the class is only meaningful if someone creates a subclass that implements some function. But then why not make that function abstract in the super-class?
I wouldn't rule out the possibility that someone might come up with some example where this makes sense, but I can't think of one. Just because it's possible to write a piece of code and that code compiles successfully doesn't mean that that it makes sense. I mean, I can write "total_price = item_price * zip_code + customer_height_in_cubits - 7.879", but that doesn't mean such a line of code would be meaningful.
Well assume that you don't care whether the methods of the abstract class are implemented or abstract, but by design it has to be abstract so that when someone extends it, they have to add more methods or override the existing ones or use as is. If they don't want to override the methods then the default behavior is already provided in that abstract class.
In this abstract class, the only criteria you enforce is - one simply cannot instantiate that class and they have to have their only version of class before using it.
So in general, abstract class with few or all methods being implemented, is much better than having an interface which has no methods implemented at all. This is based on the assumption that you are using it as a single inheritance.
Consider something similar to the NVI pattern (not sure what you'd call it in Java):
public abstract class A {
public final void doSomething() {
System.out.println("required");
doOptional();
}
protected void doOptional() {
System.out.println("optional");
}
}
public class B extends A {
#Override
protected void doOptional() {
System.out.println("overridden");
}
}
For your public API, you only expose a public final method which cannot be overridden. It performs some required work inside there and an optional method. When extending this class, you can only override doOptional().
Calling B.doSomething() will always print "required" before it proceeds.
Since doOptional() is not abstract, there's no purely code reason that class A needs to be abstract. But it might be desired for your particular project. For example, a base service that is always extended into specific sub-projects.
This can be useful for cases when the classes derived from the abstract base class must have some behaviour that is different from each other but that behaviour can not be abstracted as residing within a method that has the same signature for all the classes. Being unable to share a signature can occur if the different behaviour requires methods that are passed different primitive types. Because they use primitive types you can not use generics to express the similarity.
An abstract base class without any abstract methods is acting a bit like a marker interface, in that it is declaring that implementing classes must provide some behaviour without having that behaviour encapsulated within a new method with a signature that is the same for all implementations. You would use an abstract base class rather than a marker interface when the implementing classes have some behaviour in common, especially if the base class can implement it for the derived classes.
For example:
abstract class Sender {
protected final void beginMessage() {
...
}
protected final void endMessage() {
...
}
protected final void appendToMessage(int x) {
...
}
}
final class LongSender extends Sender {
public void send(int a, int b, int c) {
beginMessage();
appendToMessage(a);
appendToMessage(b);
appendToMessage(c);
endMessage();
}
}
final class ShortSender extends Sender {
public void send(int a) {
beginMessage();
appendToMessage(a);
endMessage();
}
}
It can be useful if you consider it an utility class.
Can have an abstract class implementing all of its methods-- with no abstract methods in it.
Eg.:
public abstract class someClass {
int a;
public someClass (int a) { this.a = a; }
public void m1 () { /* do something */ }
private void m2 () { /* do something else */ }
}
What's the advantage, if any, of having such an abstract class compared to having the same class as a concrete one instead?
One i can think of is that, when i declare it as abstract, it won't be instantiated.
however, i can have the same effect by making it concrete and its constructor(s) private.
TIA.
//==================
EDIT: One other use I can think of:
it may be extending another abstract class or implementing an interface without implementing that class's abstract methods-- although it is implementing all methods of its own. for whatever it' worth.
It has a conceptual meaning: this class has a behaviour which makes no sense on its own.
Granted, it's difficult to imagine such a scenario without well-defined extension points (i.e. abstract methods), but occasionally it will be a reasonably accurate model of your problem.
You can have something like this:
public abstract class ObjectWithId {
private final String id;
public ObjectWithId( String id ) {
this.id = id;
}
public final String getId() {
return id;
}
}
And then you can extend it to declare different types of objects that have ids. Here you have a fully specified and implemented behaviour but no restriction on any other behaviours subclasses may exhibit.
Note though that a much neater way to model the same thing is to use composition instead of inheritance.
public final class ObjectWithId<T> {
private final String id;
private final T ob;
public ObjectWithId( String id, T ob ) {
this.id = id;
this.ob = ob;
}
public String getId() {
return id;
}
public T getObject() {
return ob;
}
}
But before generics were introduced (up to Java version 1.4), this wouldn't have been as elegant and obviously better than the abstract class solution because you'd have had to trade in type safety.
you can declare to implement an interface and don't provide implementation and then each child implicitly gets interface extended
you prevent to create instance of this class
you in future provide common implementation to all children
As you pointed out, you can prevent the class from being instantiated by making it's constructor private. Othere than that, there is no benefit whatsoever. This is probably supported just to provide language completeness.
We generally use Abstraction concept with inheritance
Consider using abstract classes if any of these statements apply to
your situation:
You want to share code among several closely related classes.
To answer your question,
Why declare a class with concrete methods Abstract?
One possible reason is to support inheritance without actually creating objects
Assume you have two classes one Abstract and other Concrete
Abstract class : AbsClass
abstract class AbsClass {
int a = 5;
//Constructor
public AbsClass() {
System.out.println(a);
}
void methodA() {
System.out.println(a + 10);
}
}
and
Concrete class : ConcreteClass
class ConcreteClass {
int a = 10;
//Made the constructor Private to prevent from creating objects of this class
private ConcreteClass() {
System.out.println(a);
}
void methodA() {
System.out.println(a + 10);
}
}
The above two classes should function similarly (?) Until you try to Subclass them
class AbsImplementer extends AbsClass {
//Works fine
}
class ConcImplementer extends ConcreteClass {
//Compilation Error Implicit super constructor ConcreteClass() is not visible
}
The practical difference is that you can't create an instance of it. You would have to subclass it and create an instance of the subclass.
As to WHY you would want to do this, in practice ... I'm hard pressed to think of a good reason. You could say that the class is only meaningful if someone creates a subclass that implements some function. But then why not make that function abstract in the super-class?
I wouldn't rule out the possibility that someone might come up with some example where this makes sense, but I can't think of one. Just because it's possible to write a piece of code and that code compiles successfully doesn't mean that that it makes sense. I mean, I can write "total_price = item_price * zip_code + customer_height_in_cubits - 7.879", but that doesn't mean such a line of code would be meaningful.
Well assume that you don't care whether the methods of the abstract class are implemented or abstract, but by design it has to be abstract so that when someone extends it, they have to add more methods or override the existing ones or use as is. If they don't want to override the methods then the default behavior is already provided in that abstract class.
In this abstract class, the only criteria you enforce is - one simply cannot instantiate that class and they have to have their only version of class before using it.
So in general, abstract class with few or all methods being implemented, is much better than having an interface which has no methods implemented at all. This is based on the assumption that you are using it as a single inheritance.
Consider something similar to the NVI pattern (not sure what you'd call it in Java):
public abstract class A {
public final void doSomething() {
System.out.println("required");
doOptional();
}
protected void doOptional() {
System.out.println("optional");
}
}
public class B extends A {
#Override
protected void doOptional() {
System.out.println("overridden");
}
}
For your public API, you only expose a public final method which cannot be overridden. It performs some required work inside there and an optional method. When extending this class, you can only override doOptional().
Calling B.doSomething() will always print "required" before it proceeds.
Since doOptional() is not abstract, there's no purely code reason that class A needs to be abstract. But it might be desired for your particular project. For example, a base service that is always extended into specific sub-projects.
This can be useful for cases when the classes derived from the abstract base class must have some behaviour that is different from each other but that behaviour can not be abstracted as residing within a method that has the same signature for all the classes. Being unable to share a signature can occur if the different behaviour requires methods that are passed different primitive types. Because they use primitive types you can not use generics to express the similarity.
An abstract base class without any abstract methods is acting a bit like a marker interface, in that it is declaring that implementing classes must provide some behaviour without having that behaviour encapsulated within a new method with a signature that is the same for all implementations. You would use an abstract base class rather than a marker interface when the implementing classes have some behaviour in common, especially if the base class can implement it for the derived classes.
For example:
abstract class Sender {
protected final void beginMessage() {
...
}
protected final void endMessage() {
...
}
protected final void appendToMessage(int x) {
...
}
}
final class LongSender extends Sender {
public void send(int a, int b, int c) {
beginMessage();
appendToMessage(a);
appendToMessage(b);
appendToMessage(c);
endMessage();
}
}
final class ShortSender extends Sender {
public void send(int a) {
beginMessage();
appendToMessage(a);
endMessage();
}
}
It can be useful if you consider it an utility class.
i have an abstract class BaseClass with a public insert() method:
public abstract class BaseClass {
public void insert(Object object) {
// Do something
}
}
which is extended by many other classes. For some of those classes, however, the insert() method must have additional parameters, so that they instead of overriding it I overload the method of the base class with the parameters required, for example:
public class SampleClass extends BaseClass {
public void insert(Object object, Long param){
// Do Something
}
}
Now, if i instantiate the SampleClass class, i have two insert() methods:
SampleClass sampleClass = new SampleClass();
sampleClass.insert(Object object);
sampleClass.insert(Object object, Long param);
what i'd like to do is to hide the insert() method defined in the base class, so that just the overload would be visible:
SampleClass sampleClass = new SampleClass();
sampleClass.insert(Object object, Long param);
Could this be done in OOP?
There is no way of hiding the method. You can do this:
#Override
public void insert(Object ob) {
throw new UnsupportedOperationException("not supported");
}
but that's it.
The base class creates a contract. All subclasses are bound by that contract. Think about it this way:
BaseObject b = new SomeObjectWithoutInsert();
b.insert(...);
How is that code meant to know that it doesn't have an insert(Object) method? It can't.
Your problem sounds like a design problem. Either the classes in question shouldn't be inheriting from the base class in question or that base class shouldn't have that method. Perhaps you can take insert() out of that class, move it to a subclass and have classes that need insert(Object) extend it and those that need insert(Object, Object) extend a different subclass of the base object.
I don't believe there's a clean way to completely hide an inherited method in Java.
In cases like this, if you absolutely can't support that method, I would probably mark that method as #Obsolete in the child class, and have it throw a NotImplementedException (or whatever the equivalent exception is in Java), to discourage people from using it.
In the end, if you inherit a method that does not make sense for your child class, it could be that you really shouldn't inherit from that base class at all. It could also be that the base class is poorly designed or encompasses too much behavior, but it might be worth considering your class hierarchy. Another route to look at might be composition, where your class has a private instance of what used to be the base class, and you can choose which methods to expose by wrapping them in your own methods. (Edit: if the base class is abstract, composition might not be an option...)
As Cletus points out, this is really a design problem, in that you are trying to create a child class that does not obey the contract of its parent class.
There are rare circumstances where working around this by e.g. throwing an exception might be desirable (or at least an acceptable compromise -- for example, the Java Collections Framework) but in general it's a sign of poor design.
You may wish to read up on the Liskov substitution principle: the idea that (as Wikipedia puts it) "if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program". By overriding a method to throw an exception, or hiding it any other way, you're violating this principle.
If the contract of the base class' method was "inserts the current object, or throws an exception" (see e.g. the JavaDoc for Collection.add()) then you could argue you're not violating LSP, but if that is unexpected by most callers you may want to rethink your design on these grounds.
This sounds like a badly designed hierarchy -
If no default exists and the user shouldn't call the method at all you can mark the method as #Deprecated and throw an UnsupportedOperationException as other posters have noted. However - this is really only a runtime check. #Deprecated only throws a compiler warning and most IDEs mark it in some way, but there's no compile time prevention of this. It also really sucks because it's possible to get the child class as a parent class reference and call the method on it with no warning that it's "bad" at all. In the example below, there won't be any indication until runtime that anything's wrong.
Example:
// Abstract base builder class
public abstract class BaseClassBuilder {
public final doBuild() {
BaseClass base = getBase();
for (Object obj : getObjects() {
base.insert(obj);
}
}
protected abstract BaseClass getBase();
protected abstract Object[] getObjects();
}
// implementation using SampleClass
public class SampleClassBuilder extends BaseClassBuilder {
#Override
protected BaseClass getBase() {
return new SampleClass();
}
#Override
protected Object[] getObjects() {
Object[] obj = new Object[12];
// ...
return obj;
}
}
However, if a sensible default exists, you could mark the inherited method as final and provide the default value inside of it. This handles both the bad hierarchy, and it prevents the "unforseen circumstances" of the above example.
Example:
public abstract class BaseClass {
public void insert(Object object) {
// ...
}
}
public class SampleClass extends BaseClass {
public static final Long DEFAULT_PARAM = 0L;
public final void insert(Object object) {
this.insert(object, DEFAULT_PARAM);
}
public void insert(Object object, Long param) {
// ...
}
}
So lets say I have this interface:
public interface IBox
{
public void setSize(int size);
public int getSize();
public int getArea();
//...and so on
}
And I have a class that implements it:
public class Rectangle implements IBox
{
private int size;
//Methods here
}
If I wanted to use the interface IBox, i can't actually create an instance of it, in the way:
public static void main(String args[])
{
Ibox myBox=new Ibox();
}
right? So I'd actually have to do this:
public static void main(String args[])
{
Rectangle myBox=new Rectangle();
}
If that's true, then the only purpose of interfaces is to make sure that the class which implements an interface has got the correct methods in it as described by an interface? Or is there any other use of interfaces?
Interfaces are a way to make your code more flexible. What you do is this:
Ibox myBox=new Rectangle();
Then, later, if you decide you want to use a different kind of box (maybe there's another library, with a better kind of box), you switch your code to:
Ibox myBox=new OtherKindOfBox();
Once you get used to it, you'll find it's a great (actually essential) way to work.
Another reason is, for example, if you want to create a list of boxes and perform some operation on each one, but you want the list to contain different kinds of boxes. On each box you could do:
myBox.close()
(assuming IBox has a close() method) even though the actual class of myBox changes depending on which box you're at in the iteration.
What makes interfaces useful is not the fact that "you can change your mind and use a different implementation later and only have to change the one place where the object is created". That's a non-issue.
The real point is already in the name: they define an interface that anyone at all can implement to use all code that operates on that interface. The best example is java.util.Collections which provides all kinds of useful methods that operate exclusively on interfaces, such as sort() or reverse() for List. The point here is that this code can now be used to sort or reverse any class that implements the List interfaces - not just ArrayList and LinkedList, but also classes that you write yourself, which may be implemented in a way the people who wrote java.util.Collections never imagined.
In the same way, you can write code that operates on well-known interfaces, or interfaces you define, and other people can use your code without having to ask you to support their classes.
Another common use of interfaces is for Callbacks. For example, java.swing.table.TableCellRenderer, which allows you to influence how a Swing table displays the data in a certain column. You implement that interface, pass an instance to the JTable, and at some point during the rendering of the table, your code will get called to do its stuff.
One of the many uses I have read is where its difficult without multiple-inheritance-using-interfaces in Java :
class Animal
{
void walk() { }
....
.... //other methods and finally
void chew() { } //concentrate on this
}
Now, Imagine a case where:
class Reptile extends Animal
{
//reptile specific code here
} //not a problem here
but,
class Bird extends Animal
{
...... //other Bird specific code
} //now Birds cannot chew so this would a problem in the sense Bird classes can also call chew() method which is unwanted
Better design would be:
class Animal
{
void walk() { }
....
.... //other methods
}
Animal does not have the chew() method and instead is put in an interface as :
interface Chewable {
void chew();
}
and have Reptile class implement this and not Birds (since Birds cannot chew) :
class Reptile extends Animal implements Chewable { }
and incase of Birds simply:
class Bird extends Animal { }
The purpose of interfaces is polymorphism, a.k.a. type substitution. For example, given the following method:
public void scale(IBox b, int i) {
b.setSize(b.getSize() * i);
}
When calling the scale method, you can provide any value that is of a type that implements the IBox interface. In other words, if Rectangle and Square both implement IBox, you can provide either a Rectangle or a Square wherever an IBox is expected.
Interfaces allow statically typed languages to support polymorphism. An Object Oriented purist would insist that a language should provide inheritance, encapsulation, modularity and polymorphism in order to be a fully-featured Object Oriented language. In dynamically-typed - or duck typed - languages (like Smalltalk,) polymorphism is trivial; however, in statically typed languages (like Java or C#,) polymorphism is far from trivial (in fact, on the surface it seems to be at odds with the notion of strong typing.)
Let me demonstrate:
In a dynamically-typed (or duck typed) language (like Smalltalk), all variables are references to objects (nothing less and nothing more.) So, in Smalltalk, I can do this:
|anAnimal|
anAnimal := Pig new.
anAnimal makeNoise.
anAnimal := Cow new.
anAnimal makeNoise.
That code:
Declares a local variable called anAnimal (note that we DO NOT specify the TYPE of the variable - all variables are references to an object, no more and no less.)
Creates a new instance of the class named "Pig"
Assigns that new instance of Pig to the variable anAnimal.
Sends the message makeNoise to the pig.
Repeats the whole thing using a cow, but assigning it to the same exact variable as the Pig.
The same Java code would look something like this (making the assumption that Duck and Cow are subclasses of Animal:
Animal anAnimal = new Pig();
duck.makeNoise();
anAnimal = new Cow();
cow.makeNoise();
That's all well and good, until we introduce class Vegetable. Vegetables have some of the same behavior as Animal, but not all. For example, both Animal and Vegetable might be able to grow, but clearly vegetables don't make noise and animals cannot be harvested.
In Smalltalk, we can write this:
|aFarmObject|
aFarmObject := Cow new.
aFarmObject grow.
aFarmObject makeNoise.
aFarmObject := Corn new.
aFarmObject grow.
aFarmObject harvest.
This works perfectly well in Smalltalk because it is duck-typed (if it walks like a duck, and quacks like a duck - it is a duck.) In this case, when a message is sent to an object, a lookup is performed on the receiver's method list, and if a matching method is found, it is called. If not, some kind of NoSuchMethodError exception is thrown - but it's all done at runtime.
But in Java, a statically typed language, what type can we assign to our variable? Corn needs to inherit from Vegetable, to support grow, but cannot inherit from Animal, because it does not make noise. Cow needs to inherit from Animal to support makeNoise, but cannot inherit from Vegetable because it should not implement harvest. It looks like we need multiple inheritance - the ability to inherit from more than one class. But that turns out to be a pretty difficult language feature because of all the edge cases that pop up (what happens when more than one parallel superclass implement the same method?, etc.)
Along come interfaces...
If we make Animal and Vegetable classes, with each implementing Growable, we can declare that our Cow is Animal and our Corn is Vegetable. We can also declare that both Animal and Vegetable are Growable. That lets us write this to grow everything:
List<Growable> list = new ArrayList<Growable>();
list.add(new Cow());
list.add(new Corn());
list.add(new Pig());
for(Growable g : list) {
g.grow();
}
And it lets us do this, to make animal noises:
List<Animal> list = new ArrayList<Animal>();
list.add(new Cow());
list.add(new Pig());
for(Animal a : list) {
a.makeNoise();
}
The advantage to the duck-typed language is that you get really nice polymorphism: all a class has to do to provide behavior is provide the method. As long as everyone plays nice, and only sends messages that match defined methods, all is good. The downside is that the kind of error below isn't caught until runtime:
|aFarmObject|
aFarmObject := Corn new.
aFarmObject makeNoise. // No compiler error - not checked until runtime.
Statically-typed languages provide much better "programming by contract," because they will catch the two kinds of error below at compile-time:
// Compiler error: Corn cannot be cast to Animal.
Animal farmObject = new Corn();
farmObject makeNoise();
--
// Compiler error: Animal doesn't have the harvest message.
Animal farmObject = new Cow();
farmObject.harvest();
So....to summarize:
Interface implementation allows you to specify what kinds of things objects can do (interaction) and Class inheritance lets you specify how things should be done (implementation).
Interfaces give us many of the benefits of "true" polymorphism, without sacrificing compiler type checking.
Normally Interfaces define the interface you should use (as the name says it ;-) ). Sample
public void foo(List l) {
... do something
}
Now your function foo accepts ArrayLists, LinkedLists, ... not only one type.
The most important thing in Java is that you can implement multiple interfaces but you can only extend ONE class! Sample:
class Test extends Foo implements Comparable, Serializable, Formattable {
...
}
is possible but
class Test extends Foo, Bar, Buz {
...
}
is not!
Your code above could also be: IBox myBox = new Rectangle();. The important thing is now, that myBox ONLY contains the methods/fields from IBox and not the (possibly existing) other methods from Rectangle.
I think you understand everything Interfaces do, but you're not yet imagining the situations in which an Interface is useful.
If you're instantiating, using and releasing an object all within a narrow scope (for example, within one method call), an Interface doesn't really add anything. Like you noted, the concrete class is known.
Where Interfaces are useful is when an object needs to be created one place and returned to a caller that may not care about the implementation details. Let's change your IBox example to an Shape. Now we can have implementations of Shape such as Rectangle, Circle, Triangle, etc., The implementations of the getArea() and getSize() methods will be completely different for each concrete class.
Now you can use a factory with a variety of createShape(params) methods which will return an appropriate Shape depending on the params passed in. Obviously, the factory will know about what type of Shape is being created, but the caller won't have to care about whether it's a circle, or a square, or so on.
Now, imagine you have a variety of operations you have to perform on your shapes. Maybe you need to sort them by area, set them all to a new size, and then display them in a UI. The Shapes are all created by the factory and then can be passed to the Sorter, Sizer and Display classes very easily. If you need to add a hexagon class some time in the future, you don't have to change anything but the factory. Without the Interface, adding another shape becomes a very messy process.
you could do
Ibox myBox = new Rectangle();
that way you are using this object as Ibox and you don't care that its really Rectangle .
WHY INTERFACE??????
It starts with a dog. In particular, a pug.
The pug has various behaviors:
public class Pug {
private String name;
public Pug(String n) { name = n; }
public String getName() { return name; }
public String bark() { return "Arf!"; }
public boolean hasCurlyTail() { return true; } }
And you have a Labrador, who also has a set of behaviors.
public class Lab {
private String name;
public Lab(String n) { name = n; }
public String getName() { return name; }
public String bark() { return "Woof!"; }
public boolean hasCurlyTail() { return false; } }
We can make some pugs and labs:
Pug pug = new Pug("Spot");
Lab lab = new Lab("Fido");
And we can invoke their behaviors:
pug.bark() -> "Arf!"
lab.bark() -> "Woof!"
pug.hasCurlyTail() -> true
lab.hasCurlyTail() -> false
pug.getName() -> "Spot"
Let's say I run a dog kennel and I need to keep track of all the dogs I'm housing. I need to store my pugs and labradors in separate arrays:
public class Kennel {
Pug[] pugs = new Pug[10];
Lab[] labs = new Lab[10];
public void addPug(Pug p) { ... }
public void addLab(Lab l) { ... }
public void printDogs() { // Display names of all the dogs } }
But this is clearly not optimal. If I want to house some poodles, too, I have to change my Kennel definition to add an array of Poodles. In fact, I need a separate array for each kind of dog.
Insight: both pugs and labradors (and poodles) are types of dogs and they have the same set of behaviors. That is, we can say (for the purposes of this example) that all dogs can bark, have a name, and may or may not have a curly tail. We can use an interface to define what all dogs can do, but leave it up to the specific types of dogs to implement those particular behaviors. The interface says "here are the things that all dogs can do" but doesn't say how each behavior is done.
public interface Dog
{
public String bark();
public String getName();
public boolean hasCurlyTail(); }
Then I slightly alter the Pug and Lab classes to implement the Dog behaviors. We can say that a Pug is a Dog and a Lab is a dog.
public class Pug implements Dog {
// the rest is the same as before }
public class Lab implements Dog {
// the rest is the same as before
}
I can still instantiate Pugs and Labs as I previously did, but now I also get a new way to do it:
Dog d1 = new Pug("Spot");
Dog d2 = new Lab("Fido");
This says that d1 is not only a Dog, it's specifically a Pug. And d2 is also a Dog, specifically a Lab.
We can invoke the behaviors and they work as before:
d1.bark() -> "Arf!"
d2.bark() -> "Woof!"
d1.hasCurlyTail() -> true
d2.hasCurlyTail() -> false
d1.getName() -> "Spot"
Here's where all the extra work pays off. The Kennel class become much simpler. I need only one array and one addDog method. Both will work with any object that is a dog; that is, objects that implement the Dog interface.
public class Kennel {
Dog[] dogs = new Dog[20];
public void addDog(Dog d) { ... }
public void printDogs() {
// Display names of all the dogs } }
Here's how to use it:
Kennel k = new Kennel();
Dog d1 = new Pug("Spot");
Dog d2 = new Lab("Fido");
k.addDog(d1);
k.addDog(d2);
k.printDogs();
The last statement would display:
Spot Fido
An interface give you the ability to specify a set of behaviors that all classes that implement the interface will share in common. Consequently, we can define variables and collections (such as arrays) that don't have to know in advance what kind of specific object they will hold, only that they'll hold objects that implement the interface.
A great example of how interfaces are used is in the Collections framework. If you write a function that takes a List, then it doesn't matter if the user passes in a Vector or an ArrayList or a HashList or whatever. And you can pass that List to any function requiring a Collection or Iterable interface too.
This makes functions like Collections.sort(List list) possible, regardless of how the List is implemented.
This is the reason why Factory Patterns and other creational patterns are so popular in Java. You are correct that without them Java doesn't provide an out of the box mechanism for easy abstraction of instantiation. Still, you get abstraction everywhere where you don't create an object in your method, which should be most of your code.
As an aside, I generally encourage people to not follow the "IRealname" mechanism for naming interfaces. That's a Windows/COM thing that puts one foot in the grave of Hungarian notation and really isn't necessary (Java is already strongly typed, and the whole point of having interfaces is to have them as largely indistinguishable from class types as possible).
Don't forget that at a later date you can take an existing class, and make it implement IBox, and it will then become available to all your box-aware code.
This becomes a bit clearer if interfaces are named -able. e.g.
public interface Saveable {
....
public interface Printable {
....
etc. (Naming schemes don't always work e.g. I'm not sure Boxable is appropriate here)
the only purpose of interfaces is to make sure that the class which implements an interface has got the correct methods in it as described by an interface? Or is there any other use of interfaces?
I am updating the answer with new features of interface, which have introduced with java 8 version.
From oracle documentation page on summary of interface :
An interface declaration can contain
method signatures
default methods
static methods
constant definitions.
The only methods that have implementations are default and static methods.
Uses of interface:
To define a contract
To link unrelated classes with has a capabilities (e.g. classes implementing Serializable interface may or may not have any relation between them except implementing that interface
To provide interchangeable implementation e.g. strategy pattern
Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces
Organize helper methods in your libraries with static methods ( you can keep static methods specific to an interface in the same interface rather than in a separate class)
Some related SE questions with respect to difference between abstract class and interface and use cases with working examples:
What is the difference between an interface and abstract class?
How should I have explained the difference between an Interface and an Abstract class?
Have a look at documentation page to understand new features added in java 8 : default methods and static methods.
The purpose of interfaces is abstraction, or decoupling from implementation.
If you introduce an abstraction in your program, you don't care about the possible implementations. You are interested in what it can do and not how, and you use an interface to express this in Java.
If you have CardboardBox and HtmlBox (both of which implement IBox), you can pass both of them to any method that accepts a IBox. Even though they are both very different and not completely interchangable, methods that don't care about "open" or "resize" can still use your classes (perhaps because they care about how many pixels are needed to display something on a screen).
Interfaces where a fetature added to java to allow multiple inheritance. The developers of Java though/realized that having multiple inheritance was a "dangerous" feature, that is why the came up with the idea of an interface.
multiple inheritance is dangerous because you might have a class like the following:
class Box{
public int getSize(){
return 0;
}
public int getArea(){
return 1;
}
}
class Triangle{
public int getSize(){
return 1;
}
public int getArea(){
return 0;
}
}
class FunckyFigure extends Box, Triable{
// we do not implement the methods we will used the inherited ones
}
Which would be the method that should be called when we use
FunckyFigure.GetArea();
All the problems are solved with interfaces, because you do know you can extend the interfaces and that they wont have classing methods... ofcourse the compiler is nice and tells you if you did not implemented a methods, but I like to think that is a side effect of a more interesting idea.
Here is my understanding of interface advantage. Correct me if I am wrong.
Imagine we are developing OS and other team is developing the drivers for some devices.
So we have developed an interface StorageDevice. We have two implementations of it (FDD and HDD) provided by other developers team.
Then we have a OperatingSystem class which can call interface methods such as saveData by just passing an instance of class implemented the StorageDevice interface.
The advantage here is that we don't care about the implementation of the interface. The other team will do the job by implementing the StorageDevice interface.
package mypack;
interface StorageDevice {
void saveData (String data);
}
class FDD implements StorageDevice {
public void saveData (String data) {
System.out.println("Save to floppy drive! Data: "+data);
}
}
class HDD implements StorageDevice {
public void saveData (String data) {
System.out.println("Save to hard disk drive! Data: "+data);
}
}
class OperatingSystem {
public String name;
StorageDevice[] devices;
public OperatingSystem(String name, StorageDevice[] devices) {
this.name = name;
this.devices = devices.clone();
System.out.println("Running OS " + this.name);
System.out.println("List with storage devices available:");
for (StorageDevice s: devices) {
System.out.println(s);
}
}
public void saveSomeDataToStorageDevice (StorageDevice storage, String data) {
storage.saveData(data);
}
}
public class Main {
public static void main(String[] args) {
StorageDevice fdd0 = new FDD();
StorageDevice hdd0 = new HDD();
StorageDevice[] devs = {fdd0, hdd0};
OperatingSystem os = new OperatingSystem("Linux", devs);
os.saveSomeDataToStorageDevice(fdd0, "blah, blah, blah...");
}
}