I transitioned from Java 1.4(previous company) to Java 1.6 (new company). What I have observed that in case of 1.4 most of the proprietary frameworks were defined using interfaces and template patterns, whereas with 1.6 most of the frameworks are defined around generics.
While I am still trying to get a grip around Generics, my question is - Is this a right design approach? Interfaces make your design more flexible/decoupled. Whereas Generics, implement type safety and enforce you to pass around a specific type of class. Doesn't really help in decoupling your code. Is this correct?
One example -
public MyWizard extends SignupWizard<SignupSection, SignupObject, SignupListener, SignupView>{
}
instead the design would be more flexible if it was ..
public interface Wizardable{
public SignableSection getSection();
public SignableObject getSignableObject();
...
}
public MyWizard implements Wizardable{
....
}
I wouldn't say anything was generics vs interfaces, each have their different needs and uses. Using generic parameters in the way mentioned in the original post serves multiple purposes. It allows developers to define the base classes that make up the field object types of the class. Using this, the developer can accept class objects as parameters which they can use reflection on to create the actual objects and set the fields, or just accept the entire object to set in the first place. The problem which relates to needing class objects rather than doing new T() or such is known as type erasure.
Another benefit of using generics is that you don't need to typecast all the time when using fields or methods from a superclass -- you personally know their types, but Java doesn't have that type information stored anywhere. An additional benefit is that all your getter / setter methods can use the generic parameters and expose a more sensible front to other objects which rely on the fact that you set up specialised fields in the aforementioned object.
The problem with using interfaces to do the same thing that generics does is that you need additional methods to access the specialised types and cast them, before returning them (or check incoming types and then set fields to the objects). It's making the design more complex, and doesn't really help with decoupling at all.
As I mentioned in a comment, any subclasses will set those type parameters and expose nothing to the user. So you can have something like class MegaSignupWizard extends SignupWizard<MegaSignupSection, MegaSignupObject, MegaSignupListener, MegaSignupView> and everything remains perfectly valid with MegaSignupWizard having access to specialised methods in the classes without any need to cast. Now that's cool :)
Generics allows you to implement methods on the general type while interfaces only define the signatures. Maybe it's abused sometimes to act like Scala's trait, but mostly they serve two different purposes. If everything was an interface, there is going to be a lot of duplicated code or delegations to some helper class.
I've noticed that many of the new frameworks tend to use annotations instead of interfaces, but I haven't noticed them using generics instead of interfaces (whatever it means - please explain more).
With the help of generics, its possible to reduce some code duplication and to improve type safety, when you have one interface with generic type parameters and the same interface will work for lots of different types. The collections in the java.util package are a good example of when generics are useful.
In the case of annotations, sometimes I feel they are overused and an interface would be better - for example with an interface it's easy to know what parameters a method should take - but on other cases an annotation is more flexible and powerful.
I think it's generics and interfaces, since any interface can make use of generics itself. The problem I see when you start to use generic (abstract) classes you lose the flexibility of using composition. While there is nothing bad about inheritance as such you have to design for it and there are many pitfalls.
Take a look at Jung2 to see where Generics become really powerful. Basically, any object can be a vertex or an edge which makes for some really interesting ideas in network algorithms. You couldn't do this with just interfaces.
I'm not sure your above use looks good either. If you're extending from an object or implementing an interface you don't really want to be passing objects like that. Generics are used to implement a class with abstract type, like a collection, that could act on anything. What happens if I pass SignupWizard<int, int, int, int> which is perfectly valid?
For that particular idea, perhaps you do want to use interfaces. Have an interface defining wizardaction, each object implementing it and mywizard being able to .addaction(int position, wizardaction action). In fact that is definitely an interfaces problem.
I'd agree with the others - generics have been used when they're needed by libraries.
Related
Is there anything wrong with extending a generic class just to simplify or prevent writing redundant code?
Basically what I want to do is
class EnityGroup extends LinkedList<Entity>
{
....
}
but every example I've seen composition seems to be preferred.
What, if any, are the issues, concerns, conflicts etc that I would have to worry about.
What you are looking for is a type alias, a feature available in other programming languages (eg. C or C++). Java doesn't provide such feature.
For the type system EntityGroup is-a LinkedList<Entity> so nothing bad can happen. Every method that accepts a LinkedList<Entity> will accept an EntityGroup instance.
The only shortcoming is that the constructors are not directly available to your subclass so you are forced to redeclare them (possibly forwarding arguments to superclass constructor).
From a polymorphic point of view this is not like having a type alias, since EntityGroup is a different type which extends another type, not a different name for LinkedList<Entity>. So LinkedList.class != EntityGroup.class, this could create problems with code that uses reflection, unless written correctly to automatically detects types in the hierarchy.
Inheritance is there to enrich or specialize behavior of a class, which is not the case in this situation. You are basically using a feature to obtain something that is not meant to be obtained in this way, but by having type aliases, which unfortunately aren't available in Java.
While I am learning Haskell, I noticed its type class, which is supposed to be a great invention that originated from Haskell.
However, in the Wikipedia page on type class:
The programmer defines a type class by specifying a set of function or
constant names, together with their respective types, that must exist
for every type that belongs to the class.
Which seems rather close to Java's Interface to me (quoting Wikipedia's Interface(Java) page):
An interface in the Java programming language is an abstract type that
is used to specify an interface (in the generic sense of the term)
that classes must implement.
These two looks rather similar: type class limit a type's behavior, while interface limit a class' behavior.
I wonder what are the differences and similarities between type class in Haskell and interface in Java, or maybe they are fundamentally different?
EDIT: I noticed even haskell.org admits that they are similar. If they are so similar (or are they?), then why type class is treated with such hype?
MORE EDIT: Wow, so many great answers! I guess I'll have to let the community decide which is the best one. However, while reading the answers, all of them seem to just say that "there are many things typeclass can do while interface cannot or have to cope with generics". I cannot help but wondering, are there anything interfaces can do while typeclasses cannot? Also, I noticed that Wikipedia claims that typeclass was originally invented in the 1989 paper *"How to make ad-hoc polymorphism less ad hoc", while Haskell is still in its cradle, while Java project was started in 1991 and first released in 1995. So maybe instead of typeclass being similar to interfaces, its the other way around, that interfaces were influenced by typeclass? Are there any documents/papers support or disprove this? Thanks for all the answers, they are all very enlightening!
Thanks for all the inputs!
I would say that an interface is kind of like a type class SomeInterface t where all of the values have the type t -> whatever (where whatever does not contain t). This is because with the kind of inheritance relationship in Java and similar languages, the method called depends on the type of object they are called on, and nothing else.
That means it's really hard to make things like add :: t -> t -> t with an interface, where it is polymorphic on more than one parameter, because there's no way for the interface to specify that the argument type and return type of the method is the same type as the type of the object it is called on (i.e. the "self" type). With Generics, there are kinda ways to fake this by making an interface with generic parameter that is expected to be the same type as the object itself, like how Comparable<T> does it, where you are expected to use Foo implements Comparable<Foo> so that the compareTo(T otherobject) kind of has type t -> t -> Ordering. But that still requires the programmer to follow this rule, and also causes headaches when people want to make a function that uses this interface, they have to have recursive generic type parameters.
Also, you won't have things like empty :: t because you're not calling a function here, so it isn't a method.
What is similar between interfaces and type classes is that they name and describe a set of related operations. The operations themselves are described via their names, inputs, and outputs. Likewise there may be many implementations of these operations that will likely differ in their implementation.
With that out of the way, here are some notable differences:
Interfaces methods are always associated with an object instance. In other words, there is always an implied 'this' parameter that is the object on which the method is called. All inputs to a type class function are explicit.
An interface implementation must be defined as part of the class that implements the interface. Conversely, a type class 'instance' can be defined completely seperate from its associated type...even in another module.
In general, I think its fair to say that type classes are more powerful and flexible than interfaces. How would you define an interface for converting a string to some value or instance of the implementing type? It's certainly not impossible, but the result would not be intuitive or elegant. Have you ever wished it was possible to implement an interface for a type in some compiled library? These are both easy to accomplish with type classes.
Type classes were created as a structured way to express "ad-hoc polymorphism", which is basically the technical term for overloaded functions. A type class definition looks something like this:
class Foobar a where
foo :: a -> a -> Bool
bar :: String -> a
What this means is that, when you use apply the function foo to some arguments of a type that belong to the class Foobar, it looks up an implementation of foo specific to that type, and uses that. This is very similar to the situation with operator overloading in languages like C++/C#, except more flexible and generalized.
Interfaces serve a similar purpose in OO languages, but the underlying concept is somewhat different; OO languages come with a built-in notion of type hierarchies that Haskell simply doesn't have, which complicates matters in some ways because interfaces can involve both overloading by subtyping (i.e., calling methods on appropriate instances, subtypes implementing interfaces their supertypes do) and by flat type-based dispatch (since two classes implementing an interface may not have a common superclass that also implements it). Given the huge additional complexity introduced by subtyping, I suggest it's more helpful to think of type classes as an improved version of overloaded functions in a non-OO language.
Also worth noting is that type classes have vastly more flexible means of dispatch--interfaces generally apply only to the single class implementing it, whereas type classes are defined for a type, which can appear anywhere in the signature of the class's functions. The equivalent of this in OO interfaces would be allowing the interface to define ways to pass an object of that class to other classes, define static methods and constructors that would select an implementation based on what return type is required in calling context, define methods that take arguments of the same type as the class implementing the interface, and various other things that don't really translate at all.
In short: They serve similar purposes, but the way they work is somewhat different, and type classes are both significantly more expressive and, in some cases, simpler to use because of working on fixed types rather that pieces of an inheritance hierarchy.
I've read the above answers. I feel I can answer slightly more clearly:
A Haskell "type class" and a Java/C# "interface" or a Scala "trait" are basically analogous. There is no conceptual distinction between them but there are implementation differences:
Haskell type classes are implemented with "instances" that are separate from the data type definition. In C#/Java/Scala, the interfaces/traits must be implemented in the class definition.
Haskell type classes allow you to return a this type or self type. Scala traits do as well (this.type). Note that "self types" in Scala are a completely unrelated feature. Java/C# require a messy workaround with generics to approximate this behavior.
Haskell type classes let you define functions (including constants) without an input "this" type parameter. Java/C# interfaces and Scala traits require a "this" input parameter on all functions.
Haskell type classes let you define default implementations for functions. So do Scala traits and Java 8+ interfaces. C# can approximate something like this with extensions methods.
In Master minds of Programming, there's an interview about Haskell with Phil Wadler, the inventor of type classes, who explain the similarities between interfaces in Java and type classes in Haskell:
A Java method like:
public static <T extends Comparable<T>> T min (T x, T y)
{
if (x.compare(y) < 0)
return x;
else
return y;
}
is very similar to the Haskell method:
min :: Ord a => a -> a -> a
min x y = if x < y then x else y
So, type classes are related to interfaces, but the real correspondance would be a static method parametrized with a type as above.
Watch Phillip Wadler's talk Faith, Evolution, and Programming Languages. Wadler worked on Haskell and was a major contributor to Java Generics.
I can't speak to the "hype"-level, if it seems that way fine. But yes type classes are similar in lots of ways. One difference that I can think of is that it Haskell you can provide behavior for some of the type class's operations:
class Eq a where
(==), (/=) :: a -> a -> Bool
x /= y = not (x == y)
x == y = not (x /= y)
which shows that there are two operations, equal (==), and not-equal (/=), for things that are instances of the Eq type class. But the not-equal operation is defined in terms of equals (so that you'd only have to provide one), and vice versa.
So in probably-not-legal-Java that would be something like:
interface Equal<T> {
bool isEqual(T other) {
return !isNotEqual(other);
}
bool isNotEqual(T other) {
return !isEqual(other);
}
}
and the way that it would work is that you'd only need to provide one of those methods to implement the interface. So I'd say that the ability to provide a sort of partial implemention of the behavior you want at the interface level is a difference.
Read Software Extension and Integration with Type Classes where examples are given of how type classes can solve a number of problems that interfaces cannot.
Examples listed in the paper are:
the expression problem,
the framework integration problem,
the problem of independent extensibility,
the tyranny of the dominant decomposition, scattering and tangling.
They are similar (read: have similar use), and probably implemented similarly: polymorphic functions in Haskell take under the hood a 'vtable' listing the functions associated with the typeclass.
This table can often be deduced at compile time. This is probably less true in Java.
But this is a table of functions, not methods. Methods are bound to an object, Haskell typeclasses are not.
See them rather like Java's generics.
As Daniel says, interface implementations are defined seperately from data declarations. And as others have pointed out, there's a straightforward way to define operations that use the same free type in more than one place. So its easy to define Num as a typeclass. Thus in Haskell we get the syntactic benefits of operator overloading without actually having any magic overloaded operators -- just standard typeclasses.
Another difference is that you can use methods based on a type, even when you don't have a concrete value of that type hanging around yet!
For example, read :: Read a => String -> a. So if you have enough other type information hanging around about how you'll use the result of a "read", you can let the compiler figure out which dictionary to use for you.
You can also do things like instance (Read a) => Read [a] where... which lets you define a read instance for any list of readable things. I don't think that's quite possible in Java.
And all this is just standard single-parameter typeclasses with no trickery going on. Once we introduce multi-parameter typeclasses, then a whole new world of possibilities opens up, and even more so with functional dependencies and type families, which let you embed much more information and computation in the type system.
Sometimes we have several classes that have some methods with the same signature, but that don't correspond to a declared Java interface. For example, both JTextField and JButton (among several others in javax.swing.*) have a method
public void addActionListener(ActionListener l)
Now, suppose I wish to do something with objects that have that method; then, I'd like to have an interface (or perhaps to define it myself), e.g.
public interface CanAddActionListener {
public void addActionListener(ActionListener l);
}
so that I could write:
public void myMethod(CanAddActionListener aaa, ActionListener li) {
aaa.addActionListener(li);
....
But, sadly, I can't:
JButton button;
ActionListener li;
...
this.myMethod((CanAddActionListener)button,li);
This cast would be illegal. The compiler knows that JButton is not a CanAddActionListener, because the class has not declared to implement that interface ... however it "actually" implements it.
This is sometimes an inconvenience - and Java itself has modified several core classes to implement a new interface made of old methods (String implements CharSequence, for example).
My question is: why this is so? I understand the utility of declaring that a class implements an interface. But anyway, looking at my example, why can't the compiler deduce that the class JButton "satisfies" the interface declaration (looking inside it) and accept the cast? Is it an issue of compiler efficiency or there are more fundamental problems?
My summary of the answers: This is a case in which Java could have made allowance for some "structural typing" (sort of a duck typing - but checked at compile time). It didn't. Apart from some (unclear for me) performance and implementations difficulties, there is a much more fundamental concept here: In Java, the declaration of an interface (and in general, of everything) is not meant to be merely structural (to have methods with these signatures) but semantical: the methods are supposed to implement some specific behavior/intent. So, a class which structurally satisfies some interface (i.e., it has the methods with the required signatures) does not necessarily satisfies it semantically (an extreme example: recall the "marker interfaces", which do not even have methods!). Hence, Java can assert that a class implements an interface because (and only because) this has been explicitly declared. Other languages (Go, Scala) have other philosophies.
Java's design choice to make implementing classes expressly declare the interface they implement is just that -- a design choice. To be sure, the JVM has been optimized for this choice and implementing another choice (say, Scala's structural typing) may now come at additional cost unless and until some new JVM instructions are added.
So what exactly is the design choice about? It all comes down to the semantics of methods. Consider: are the following methods semantically the same?
draw(String graphicalShapeName)
draw(String handgunName)
draw(String playingCardName)
All three methods have the signature draw(String). A human might infer that they have different semantics from the parameter names, or by reading some documentation. Is there any way for the machine to tell that they are different?
Java's design choice is to demand that the developer of a class explicitly state that a method conforms to the semantics of a pre-defined interface:
interface GraphicalDisplay {
...
void draw(String graphicalShapeName);
...
}
class JavascriptCanvas implements GraphicalDisplay {
...
public void draw(String shape);
...
}
There is no doubt that the draw method in JavascriptCanvas is intended to match the draw method for a graphical display. If one attempted to pass an object that was going to pull out a handgun, the machine can detect the error.
Go's design choice is more liberal and allows interfaces to be defined after the fact. A concrete class need not declare what interfaces it implements. Rather, the designer of a new card game component may declare that an object that supplies playing cards must have a method that matches the signature draw(String). This has the advantage that any existing class with that method can be used without having to change its source code, but the disadvantage that the class might pull out a handgun instead of a playing card.
The design choice of duck-typing languages is to dispense with formal interfaces altogether and simply match on method signatures. Any concept of interface (or "protocol") is purely idiomatic, with no direct language support.
These are but three of many possible design choices. The three can be glibly summarized like this:
Java: the programmer must explicitly declare his intent, and the machine will check it. The assumption is that the programmer is likely to make a semantic mistake (graphics / handgun / card).
Go: the programmer must declare at least part of his intent, but the machine has less to go on when checking it. The assumption is that the programmer is likely to might make a clerical mistake (integer / string), but not likely to make a semantic mistake (graphics / handgun / card).
Duck-typing: the programmer needn't express any intent, and there is nothing for the machine to check. The assumption is that programmer is unlikely to make either a clerical or semantic mistake.
It is beyond the scope of this answer to address whether interfaces, and typing in general, are adequate to test for clerical and semantic mistakes. A full discussion would have to consider build-time compiler technology, automated testing methodology, run-time/hot-spot compilation and a host of other issues.
It is acknowledged that the draw(String) example are deliberately exaggerated to make a point. Real examples would involve richer types that would give more clues to disambiguate the methods.
Why can't the compiler deduce that the class JButton "satisfies" the interface declaration (looking inside it) and accept the cast? Is it an issue of compiler efficiency or there are more fundamental problems?
It is a more fundamental issue.
The point of an interface is to specify that there is a common API / set of behaviors that a number of classes support. So, when a class is declared as implements SomeInterface, any methods in the class whose signatures match method signatures in the interface are assumed to be methods that provide that behavior.
By contrast, if the language simply matched methods based on signatures ... irrespective of the interfaces ... then we'd be liable to get false matches, when two methods with the same signature actually mean / do something semantically unrelated.
(The name for the latter approach is "duck typing" ... and Java doesn't support it.)
The Wikipedia page on type systems says that duck typing is neither "nominative typing" or "structural typing". By contrast, Pierce doesn't even mention "duck typing", but he defines nominative (or "nominal" as he calls it) typing and structural typing as follows:
"Type systems like Java's, in which names [of types] are significant and subtyping is explicitly declared, are called nominal. Type systems like most of the ones in this book in which names are inessential and subtyping is defined directly on the structure of the types, are called structural."
So by Pierce's definition, duck typing is a form of structural typing, albeit one that is typically implemented using runtime checks. (Pierce's definitions are independent of compile-time versus runtime-checking.)
Reference:
"Types and Programming Languages" - Benjamin C Pierce, MIT Press, 2002, ISBN 0-26216209-1.
Likely it's a performance feature.
Since Java is statically typed, the compiler can assert the conformance of a class to an identified interface. Once validated, that assertion can be represented in the compiled class as simply a reference to the conforming interface definition.
Later, at runtime, when an object has its Class cast to the interface type, all the runtime needs to do is check the meta data of the class to see if the class that it is being cast too is compatible (via the interface or the inheritance hierarchy).
This is a reasonably cheap check to perform since the compiler has done most of the work.
Mind, it's not authoritative. A class can SAY that it conforms to an interface, but that doesn't mean that the actual method send about to be executed will actually work. The conforming class may well be out of date and the method may simply not exist.
But a key component to the performance of java is that while it still must actually do a form of dynamic method dispatch at runtime, there's a contract that the method isn't going to suddenly vanish behind the runtimes back. So once the method is located, its location can be cached in the future. In contrast to a dynamic language where methods may come and go, and they must continue to try and hunt the methods down each time one is invoked. Obviously, dynamic languages have mechanisms to make this perform well.
Now, if the runtime were to ascertain that an object complies with an interface by doing all of the work itself, you can see how much more expensive that can be, especially with a large interface. A JDBC ResultSet, for example, has over 140 methods and such in it.
Duck typing is effectively dynamic interface matching. Check what methods are called on an object, and map it at runtime.
All of that kind of information can be cached, and built at runtime, etc. All of this can (and is in other languages), but having much of this done at compile time is actually quite efficient both on the runtimes CPU and its memory. While we use Java with multi GB heaps for long running servers, it's actually pretty suitable for small deployments and lean runtimes. Even outside of J2ME. So, there is still motivation to try and keep the runtime footprint as lean as possible.
Duck typing can be dangerous for the reasons Stephen C discussed, but it is not necessarily the evil that breaks all static typing. A static and more safe version of duck typing lies at the heart of Go's type system, and a version is available in Scala where it is called "structural typing." These versions still perform a compile time check to make sure the object obeys the requirements, but have potential problems because they break the design paradigm that has implementing an interface always an intentional decision.
See http://markthomas.info/blog/?p=66 and http://programming-scala.labs.oreilly.com/ch12.html and http://beust.com/weblog/2008/02/11/structural-typing-vs-duck-typing/ for a discusion of the Scala feature.
I can't say I know why certain design decisions were made by the Java development team. I also caveat my answer with the fact that those individuals are far smarter than I'll ever be with regards to software development and (particularly) language design. But, here's a crack at trying to answer your question.
In order to understand why they may not have chosen to use an interface like "CanAddActionListener" you have to look at the advantages of NOT using an interface and, instead, preferring abstract (and, ultimately, concrete) classes.
As you may know, when declaring abstract functionality, you can provide default functionality to subclasses. Okay...so what? Big deal, right? Well, particularly in the case of designing a language, it is a big deal. When designing a language, you will need to maintain those base classes over the life of the language (and you can be sure that there will be changes as your language evolves). If you had chosen to use interfaces, instead of providing base functionality in an abstract class, any class that implements the interface will break. This is particularly important after publication - once customers (developers in this case) start using your libraries, you can't change up the interfaces on a whim or you are going to have a lot of pissed of developers!
So, my guess is that the Java development team fully realized that many of their AbstractJ* classes shared the same method names, it would not be advantageous in having them share a common interface as it would make their API rigid and inflexible.
To sum it up (thank you to this site here):
Abstract classes can easily be extended by adding new (non-abstract) methods.
An interface cannot be modified without breaking its contract with the classes that implement it. Once an interface has been shipped, its member set is permanently fixed. An API based on interfaces can only be extended by adding new interfaces.
Of course, this is not to say that you could do something like this in your own code, (extend AbstractJButton and implement CanAddActionListener interface) but be aware of the pitfalls in doing so.
Interfaces represent a form of substitution class. A reference of type which implements or inherits from a particular interface may be passed to a method which expects that interface type. An interface will generally not only specify that all implementing classes must have methods with certain names and signatures, but it will generally also have an associated contract which specifies that all legitimate implementing classes must have methods with certain names and signatures, which behave in certain designated ways. It is entirely possible that even if two interfaces contain members with the same names and signatures, an implementation may satisfy the contract of one but not the other.
As a simple example, if one were designing a framework from scratch, one might start out with an Enumerable<T> interface (which can be used as often as desired to create an enumerator which will output a sequence of T's, but different requests may yield different sequences), but then derive from it an interface ImmutableEnumerable<T> which would behave as above but guarantee that every request would return the same sequence. A mutable collection type would support all of the members required for ImmutableEnumerable<T>, but since requests for enumeration received after a mutation would report a different sequence from requests made before, it would not abide by the ImmutableEnumerable contract.
The ability of an interface to be regarded as encapsulating a contract beyond the signatures of its members is one of the things that makes interface-based programming more semantically powerful than simple duck-typing.
Well I was going to ask what the difference is but it's been answered before. But now I'm asking why did they make these differences? (I'm speaking about java here, I don't know if the same applies to other languages)
The two things seem very similar. Abstract classes can define a method body whilst interfaces can't, but multiple interfaces can be inherited. So why didn't they (by 'they' I mean Sun when they wrote Java) make one thing where you can write a method body and this type can be inherited more than once by a class.
Is there some advantage in not being able to write a method body, or extend multiple times that I'm not seeing?
Because allowing classes to inherit multiple implementations for the same method signature leads to the obvious question, which one should be used at runtime.
Java avoids this by supporting multiple inheritance only for interfaces. The signatures declared in each interface can be combined much more easily (Java basically uses the union of all methods)
Multiple inheritance in C++ leads to semantic ambiguities like the diamond inheritance problem. MI is quite powerful, but has complex consequences.
Making interfaces a special case also raises the visibility of the concept as a means of information hiding and reducing program complexity. In C++, defining pure abstract bases is a sign of a mature programmer. In Java, you encounter them at a much earlier stage in the evolution of a programmer.
Multiple inheritance is more difficult to implement in a language (compiler really) as it can lead to certain issues. These issues have been discussed here before: What is the exact problem with multiple inheritance.
I've always assumed this was a compromise in Java. Interfaces allow a class to fulfill multiple contracts without the headache of multiple inheritance.
Consider this example:
public abstract class Engine
{
public abstract void switchPowerOn();
public abstract void sprinkleSomeFuel();
public abstract void ignite();
public final void start()
{
switchPowerOn();
sprinkleSomeFuel();
ignite();
}
}
Abstract class can help you with having solid base methods which can or cannot be overriden, but in these methods it uses abstract methos to provide you an opportunity to do your specific thing. In my example different engines have different implementations of how they switch power on, sprinkling some fuel for the ignition, and doing the ignition, however the starting sequence of the engine stays always the same.
That pattern is called "Form Template Method" and is quite frankly the only sensible usage of abstract classes in Java for me.
Making them one thing is the route that the Scala guys took with Traits which is an interface that can have methods and supports multiple inheritance.
I think interfaces, for me, are clean in that they only specify requirements (design by contract) whereas abstract classes define common behaviour (implementation), so a different tool for a different job? Interfaces probably allow more efficient code generation during compile time as well?
The other approach you are describing is the approach used by C++ (mixins for example). The issues related to such "multiple inheritance" are quite complex, and has several critics in C++.
Inheritance means you inherit the nature (meaning) and responsibility (behaviour) of the parent class, while interface implementation means you fulfill a contract (e.g. Serializable), which may have nothing to do with the core nature or responsibility of the class.
Abstract class let you define a nature that you want to be generic and not directly instanciable, because it must be specialized. You know how to perform some high-level tasks (e.g. make a decision according to some parameters), but you don't know the details for some lower-level actions (e.g. compute some intermediary parameters), because it depends on implementation choices. An alternative for solving this problem is the Strategy design pattern. It is more flexible, allowing run-time strategy switching and Null behaviour, yet it is more complex (and runtime swtiching is not always necessary). Moreover, you might lose some meaning & typing facilities (polymorphism & type-checking becomes a bit harder because the Strategy is a component, not the object itself).
Abstract class = is-a, Strategy = has-a
Edit: as for multiple inheritance, see Pontus Gagge's answer.
This question already has answers here:
What does it mean to "program to an interface"?
(33 answers)
Closed 9 years ago.
I want to solidify my understanding of the "coding to interface" concept. As I understand it, one creates interfaces to delineate expected functionality, and then implements these "contracts" in concrete classes. To use the interface one can simply call the methods on an instance of the concrete class.
The obvious benefit is knowing of the functionality provided by the concrete class, irrespective of its specific implementation.
Based on the above:
Are there any fallacies in my understanding of "coding to interfaces"?
Are there any benefits of coding to interfaces that I missed?
Thanks.
Just one possible correction:
To use the interface one can simply call the methods on an instance of the concrete class.
One would call the methods on a reference of the type interface, which happens to use the concrete class as implementation:
List<String> l = new ArrayList<String>();
l.add("foo");
l.add("bar");
If you decided to switch to another List implementation, the client code works without change:
List<String> l = new LinkedList<String>();
This is especially useful for hiding implementation details, auto generating proxies, etc.
You'll find that frameworks like spring and guice encourage programming to an interface. It's the basis for ideas like aspect-oriented programming, auto generated proxies for transaction management, etc.
Your understanding seems to be right on. Your co-worker just swung by your desk and has all the latest pics of the christmas party starring your drunk boss loaded onto his thumbdrive. Your co-worker and you do not think twice about how this thumbdrive works, to you its a black box but you know it works because of the USB interface.
It doesn't matter whether it's a SanDisk or a Titanium (not even sure that is a brand), size / color don't matter either. In fact, the only thing that matters is that it is not broken (readable) and that it plugs into USB.
Your USB thumbdrive abides by a contract, it is essentially an interface. One can assume it fulfills some very basic duties:
Plugs into USB
Abides by the contract method CopyDataTo:
public Interface IUSB {
void CopyDataTo(string somePath); //used to copy data from the thumbnail drive to...
}
Abides by the contract method CopyDataFrom:
public Interface IUSB {
void CopyDataFrom(); //used to copy data from your PC to the thumbnail drive
}
Ok maybe not those methods but the IUSB interface is just a contract that the thumbnail drive vendors have to abide by to ensure functionality across various platforms / vendors. So SanDisk makes their thumbdrive by the interface:
public class SanDiskUSB : IUSB
{
//todo: define methods of the interface here
}
Ari, I think you already have a solid understanding (from what it sounds like) about how interfaces work.
The main advantage is that the use of an interface loosely couples a class with it's dependencies. You can then change a class, or implement a new concrete interface implementation without ever having to change the classes which depend on it.
To use the interface one can simply call the methods on an instance of the concrete class.
Typically you would have a variable typed to the interface type, thus allowing only access to the methods defined in the interface.
The obvious benefit is knowing of the functionality provided by the concrete class, irrespective of its specific implementation.
Sort of. Most importantly, it allows you to write APIs that take parameters with interface types. Users of the API can then pass in their own classes (which implement those interfaces) and you code will work on those classes even though they didn't exist yet when it was written (such as java.util.Arrays.sort() being able to sort anything that implements Comparable or comes with a suitable Comparator).
From a design perspective, interfaces allow/enforce a clear separation between API contracts and implementation details.
The aim of coding against interfaces is to decouple your code from the concrete implementation in use. That is, your code will not make assumptions about the concrete type, only the interface. Consequently, the concrete implementation can be exchanged without needing to adjust your code.
You didn't list the part about how you get an implementation of the interface, which is important. If you explicitly instantiate the implementing class with a constructor then your code is tied to that implementation. You can use a factory to get an instance for you but then you're as tied to the factory as you were before to the implementing class. Your third alternative is to use dependency injection, which is having a factory plug the implementing object into the object that uses it, in which case you escape having the class that uses the object being tied to the implementing class or to a factory.
I think you may have hinted at this, but I believe one of the biggest benefits of coding to an interface is that you are breaking dependency on concrete implementation. You can achieve loose coupling and make it easier to switch out specific implementations without changing much code. If you are just learning, I would take a look at various design patterns and how they solve problems by coding to interfaces. Reading the book Head First: Design Patterns really helped things click for me.
As I understand it, one creates interfaces to delineate expected functionality, and then implements these "contracts" in concrete classes.
The only sort of mutation i see in your thinking is this - You're going to call out expected contracts, not expected functionality. The functionality is implemented in the concrete classes. The interface only states that you will be able to call something that implements the interface with the expected method signatures. Functionality is hidden from the calling object.
This will allow you to stretch your thinking into polymorphism as follows.
SoundMaker sm = new Duck();<br/>
SoundMaker sm1 = new ThunderousCloud();
sm.makeSound(); // quack, calls all sorts of stuff like larynx, etc.<br/>
sm1.makeSound(); // BOOM!, completely different operations here...