Difference between Java Interfaces and Python Mixin? - java

I have been reading about Python-Mixin and come to know that it adds some features (methods) to class. Similarly, Java-Interfaces also provide methods to class.
Only difference, I could see is that Java-interfaces are abstract methods and Python-Mixin carry implementation.
Any other differences ?

Well, the 'abstract methods' part is quite important.
Java is strongly typed. By specifying the interfaces in the type definition, you use them to construct the signature of the new type. After the type definition, you have promised that this new type (or some sub-class) will eventually implement all the functions that were defined in the various interfaces you specified.
Therefore, an interface DOES NOT really add any methods to a class, since it doesn't provide a method implementation. It just adds to the signature/promise of the class.
Python, however, is not strongly typed. The 'signature' of the type doesn't really matter, since it simply checks at run time whether the method you wish to call is actually present.
Therefore, in Python the mixin is indeed about adding methods and functionality to a class. It is not at all concerned with the type signature.
In summary:
Java Interfaces -> Functions are NOT added, signature IS extended.
Python mixins -> Functions ARE added, signature doesn't matter.

Related

Java. How to prevent assigning a method reference to functional interface type argument?

Beginning with Java SE 8, if the formal parameter of a method is a functional interface, the argument can be either an object implementing that interface or a reference to some method. It means that the argument can also be a reference to a method that is not logically related to the interface's purpose. Is it possible to force the argument to be only an object implementing the interface, but not to be a method reference? Although it is possible to make the interface non-functional by adding a second abstract method, that additional method nevertheless should be implemented. Is there another way?
Is it possible to force the argument to be only an object implementing the interface, but not to be a method reference?
There is not.
Although it is possible to make the interface non-functional by adding a second abstract method, that additional method nevertheless should be implemented. Is there another way?
Indeed, that's the downside of doing that. You can't provide a default implementation, as an interface that has exactly 1 non-defaulted method is considered a FunctionalInterface, and you can't decree it to be not so.
What you can do, however, is turn that interface into an abstract class, which aren't eligible for being supplied in lambda/methodref form.
More generally, don't fight java features. If someone uses a method ref, they know what they are doing. Or they don't, but if they are just stumbling about without a clue, trust me, you can't stop an idiot from ruining a code base by designing good APIs and adding every linter rule you manage to scrounge together. Idiots are far too inventive to be stopped by mere mortals.

Could we have Polymorphism without forcing classes to implement an interface?

Assume that we have an interface called Animal that have two methods called move() and makeSound().
This means we can send the messages move() and makeSound() on a variable of type Animal, and we can only assign objects of classes that implement Animal to a variable of type Animal.
Now my question is, could Java have not forced classes that want to use Polymorphism to implement an interface?
For example, why didn't Java implement Polymorphism like the following:
We would just create an Animal interface and then we would be able to assign whatever object we want to a variable of type Animal as long as that object have the methods move() and makeSound(), for example:
Animal animal1;
/* The Java compiler will check if Dog have the methods move() and makeSound(), if yes then
compile, if no then show a compilation error */
animal1 = new Dog();
animal1.move();
animal1.makeSound();
Note: I took Java as an example, but I am talking in general about all OOP languages. Also, I know that we can have Polymorphism using a subclass that inherits from a superclass (but this is basically the same idea as using an interface).
There are a number of different ways to get polymorphism. The one you are most familiar with is inclusion polymorphism (also known as subtype polymorphism), where the programmer explicitly says "X is-a Y" via some sort of extends clause. You see this in Java and C#; both give you the choice of having such an is-a for both representation and API (extends), or only for API (implements).
There is also parametric polymorphism, which you have probably seen as generics: defining a family of types Foo<T> with a single declaration. You see this in Java/C#/Scala (generics), C++ (templates), Haskell (type classes), etc.
Some languages have "duck typing", where, rather than looking at the declaration ("X is-a Y"), they are willing to determine typing structurally. If a contract says "to be an Iterator, you have to have hasNext() and next() methods", then under this interpretation, any class that provides these two methods is an Iterator, regardless of whether it said so or not. This comports with the case you describe; this was a choice open to the Java designers.
Languages with pattern matching or runtime reflection can exhibit a form of ad-hoc polymorphism (also known as data-driven polymorphism), where you can define polymorphic behavior over unrelated types, such as:
int length(Object o) {
return switch (o) {
case String s -> s.length();
case Object[] os -> os.length;
case Collection c -> c.size();
...
};
}
Here, length is polymorphic over an ad-hoc set of types.
It is also possible to have an explicit declaration of "X is-a Y" without putting this in the declaration of X. Haskell's type classes do this, where, rather than X declaring "I'm a Y", there's a separate declaration of an instance that explicitly says "X is a Y (and here is how to map X functionality to Y functionality if it is not obvious to the compiler.)" Such instances are often called witnesses; it is a witness to the Y-hood of X. Clojure's protocols are similar, and Scala's implicit parameters play a similar role ("find me a witness to CanCopyFrom[A,B], or fail at compile time").
The point of all this is that there are many ways to get polymorphism, and some languages pick their favorite, others support more than one, etc.
If your question is why did Java choose explicit subtyping rather than duck typing, the answer is fairly clear: Java was a language designed for building large systems (as was C++) out of components, and components want strong checking at their boundaries. A loosey-goosey match because the two sides happen to have methods with the same name is a less reliable means of establishing programmer intent than an explicit declaration. Additionally, one of the core design principles of the Java language is "reading code is more important than writing code." It may be more work to declare "implements Iterator" (but not a lot more), but it makes it much more clear to readers what your design intent was.
So, this is a tradeoff of what we might now call "ceremony" for greater reliability and more clear capture of design intent.
The approach you're describing is called "structural subtyping", and it is not only possible, but actually in use; for example, it is used by Go and TypeScript.
Per the Go Programming Language Specification:
A variable of interface type can store a value of any type with a method set that is any superset of the interface. […]
A type implements any interface comprising any subset of its methods and may therefore implement several distinct interfaces. For instance, all types implement the empty interface:
interface{}
[link]
Per the TypeScript documentation:
Type compatibility in TypeScript is based on structural subtyping. Structural typing is a way of relating types based solely on their members. This is in contrast with nominal typing. Consider the following code:
interface Named {
name: string;
}
class Person {
name: string;
}
let p: Named;
// OK, because of structural typing
p = new Person();
In nominally-typed languages like C# or Java, the equivalent code would be an error because the Person class does not explicitly describe itself as being an implementer of the Named interface.
[link]
Note: I took Java as an example, but I am talking in general about all OOP languages.
I'm not sure it's possible to talk "in general about all OOP languages", because there are so many, and they work in many different ways. Your question makes sense for Java, but it wouldn't make sense for Go or TypeScript (since as you see, it has exactly the feature you'd be claiming it doesn't), nor for non-statically-typed OO as in Python or JavaScript (since they don't have the notion of "a variable of type Animal").
ETA: In a follow-up comment, you write:
Since it was possible for Java to not force classes to [explicitly] implement an interface, then why did Java force classes to [explicitly] implement an interface?
I can't say for certain; the first edition of the Java Language Specification [link] explicitly called this out, but didn't indicate the rationale:
It is not sufficient that the class happen to implement all the abstract methods of the interface; the class or one of its superclasses must actually be declared to implement the interface, or else the class is not considered to implement the interface. [p. 183]
However, I think the main reason was probably that interfaces are intended to have a meaning, which often goes beyond what's explicitly indicated in the method signatures. For example:
java.util.List, in addition to specifying various methods of its own, also specifies the behavior of equals and hashCode, instructing implementations to override the implementations provided by java.lang.Object and implement the specified behavior. If it were possible to "accidentally" implement java.util.List, then that instruction would be meaningless, because implementations might not even "know" that they were implementations.
java.io.Serializable has no methods at all; it's just a "marker" interface to tell the Java Serialization API that this class is OK with being serialized and deserialized. In Go, such an interface would be meaningless, because every type would automatically implement it.
Some other (IMHO less-significant) possible reasons:
Java method signatures are a bit more complicated than Go method signatures, in that they can also declare exceptions, and in that Java allows method overloading (multiple methods with the same name but different signatures). These features make it more likely that a class accidentally fails to implement an interface it's supposed to. When that happens, Java's current approach means that you get a single error-message in the place where you define the class, instead of hundreds of error-messages throughout your program in every place where you've written Animal animal = new Cat().
Interfaces are allowed to have static fields, which classes inherit (rather than needing to implement). I'm not sure how this would work if classes didn't explicitly indicate which interfaces they implement.
The current approach allows the subtyping relationship to be determined completely at compile-time; by contrast, if something like Animal animal = (Animal) obj; or if (obj instanceof Animal) were allowed, then the runtime would need to analyze obj's runtime-type on the fly to determine if it conforms to the Animal interface. (This also means that adding a method to the Animal interface could potentially cause runtime failures rather than compile-time failures.)
Even just within the compiler, the current approach may simplify some things by letting the compiler verify in one place that the class satisfies the interface, and then just use that fact everywhere that an implicit or explicit conversion appears. (This is related to my comment above about clearer error-messages.)
. . . but, again, this is just me speculating. I think I'm probably in the right ballpark, but a lot of things go into language design, and there could easily have been major considerations that would never occur to me.
Yes, this behavior is implemented with a structural type system. As expressed in a different answer, Go is one language which support structural typing.
By checking the language comparison by type system wiki, you can find other languages which support a structural type system.
Java uses a nominal type system, which requires types to be explicitly defined.
Asking why Java uses a nominal type system would be like asking why is statically typed. There are pros and cons to both, and language developers choose which strategies fit the philosophy of the language.

Override an interface?

I am creating a mod for the game Minecraft, which has an interface to implement in-game commands. I need the mod to implement that interface, but override one of its methods with a non-compatible method (different return type). But I need to prevent a situation where other classes that implement that interface will not work or not be recognized by the game.
I think this would require overriding the interface with a new interface that is the same as the original, but with an overloaded version of that method to support the mod's needs. Is this possible (or is there another way I can accomplish this?)
One way to think about interfaces is as a contract.
Implementing classes must strictly adhere to this contract.
This means that the method signatures (including return values and parameter) must match exactly.
The entire point of interfaces is to define the interaction without strictly knowing the implementation.
If the interaction you are looking to implement is different then it's possible that you are trying to use something in a way it wasn't intended for.
Even if it is possible to subclass an interface, it's going to quickly get messy.
It's probably in you best interest to create a new interface (with all the other methods the same).
Since it's not going to be comparable with classes that use interface A, you are saving yourself trouble by separating it entirely.
The interfaces supplied by Mojang/forge team are intended for use within the mojang/forge code. They expect the result types to be returned that the interfaces return. If they don't get that as defined by the contract/interface the code will crash/not compile.
It seems as if you are trying to use an interface for a particular purpose for an own project/api.
Consider writing a new interface specifically for the purpose you intend to use it for. Don't modify core interfaces.
A class can inherit multiple interfaces, so that's not an issue. You can implement AND the forge/mojang interface AND your own.
You can implement the mod class. Then override the method. Also write another method which will overload the method in your implemented class. That way you won't have to change the interface.

Extending generic collection

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.

Why interfaces must be declared in Java?

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.

Categories