Is groovy's extension module feature a hybrid form of java's inheritance feature? Why are the extension-module needs to be declared as static?
Short answer is I think yes. It is a bit difficult to answer clearly, since the inheritance for the extension methods is done completely by the runtime (and the static compiler). As such it has nothing to do with how Java does inheritance.
To answer the second question... They are static, because for situations in which you need state you usually use the meta class. Extension methods are initially thought of as convenience methods or to make the API more Groovy. As such, they are a special form of methods added to the meta class. You can see them as simplified version. But that also means they don't have all the abilities. Implementing extension methods, that can keep local state on a per "self"-object basis (basically what fields/properties would do) is actually difficult to do efficient... but you could always use per instance meta classes for this.
For all extensive purposes they are syntactic sugar so that a static method appears to be more OOP like. There is no inheritance because static methods in Java and Groovy do not participate in inheritance (that is classes do not inherit static methods).
The methods need to be static because the compiler does not know how to instantiate the surrounding class of the extension method.
However I believe there are languages that do allow for methods to be defined outside of the enclosing class and do some sort inheritance but not many do not (I believe CLOS and Dylan do). Also they are many languages that appear to allow methods to be added but the type of "object" is actually changed/hidden to some other type. This is called adhoc polymorphism (e.g. Clojure, Haskell, sort of Golang and sort of Scala) but again has nothing to do with inclusional polymorphism (Java inheritance).
Unfortunately the reference documentation and other docs don't define the semantics of extension methods:
Q. Can they override instance methods?
I tested extension methods via use Category methods and metaClass expando methods. Neither approach overrides instance methods. I didn't test extension modules installed via module descriptor.
Q. Can they be overridden by extension methods on subclasses?
I tested that, too. use methods and metaClass extension methods don't get overridden by extension methods on subclasses.
Q. Can they call inherited super methods?
No, since they're implemented via static methods.
Q. Can they call private methods?
Experiments showed that they can, surprisingly.
Q. Can they access private instance variables?
No, since they're implemented via static methods.
Q. Are they callable from Java methods?
Maybe, if the extension module is on the classpath when compiling the calling code. I didn't test it.
Conclusion: Extension methods are not a form of inheritance. They seem to be a dynamic form of Universal Function Call Syntax (UFCS), that is, when the language can't find a method variable.foo(arguments) it looks for a static extension function foo(variable, arguments) to call. [Please correct my hypothesis if wrong!]
You asked why they're defined as static. That seems to match the semantics: A static function that's not involved in inheritance, although its calling syntax makes it look like a convenient method call.
You can write an extension method like an instance method using the #groovy.lang.Category annotation. That does AST transformations at compile time to turn it into a suitable static method.
Also see Groovy traits. That is a form of (mixin) inheritance.
Related
Java allows constructors of non-final classes to invoke any instance methods, even if those methods are abstract or non-final.
This is recognized as a bad practice (see., e.g., Effective Java 2nd Edition, Item 17), and isn't possible in C++ because of the defined constructor order.
My question is why this was allowed to begin with in the design of the Java language? It seemed like it could have been forbidden as a language restriction. Are there cases where doing this is necessary?
The Java language allows it because there is (was) no clear, uncontroversial reason to forbid it, specially if you consider that today's Java best practices were not necessarily known at the time the language was originally designed.
Note that a constructor calling an abstract or non-final method does work, because a subclass could override said method, and because the constructor may be executing on a newly-created instance of a subclass (due to constructor execution order from subclass to super class).
As far as I can tell, there is no case where doing it is necessary. But surely some third-party libraries out there do it, even if it is known to be a bad practice.
Say I am using a Java library that has the following method
public static SomeInterface foo();
The interface SomeInterface has multiple implementations, some of which are protected within the library's package. One of these implementation is TheProtectedClass
What would be the best way to check if the object returned by foo() is an instance of TheProtectedClass?
My current plan is to create an Utils class that lives within my project but in the same package as the protected class. This Utils can refer to TheProtectedClass since it is in the same package and thus it can check if an object is instanceof TheProtectedClass.
Any other ideas?
EDIT: Some people are asking "why" so here is more context.
I am using jOOQ and in some part of my code, I want to know if the Field instance that I have is an instance of Lower.
Currently, I use field.getName().equals("lower") but this isn't as robust as I'd like it to be.
I realize that since Lower is a protected class, it isn't part of the API and that it can change but I am ok with that.
Class.forName("TheProtectedClass").isAssignableFrom(foo())
although it is a bad idea for many reasons. You're breaking the encapsulation and the abstraction here. If it's package-private, you shouldn't have to concern with it outside. If it's protected, you should explicitly inherit from it and use the API provided by class for this case.
The less obvious but more correct solution is to get an instance of TheProtectedClass, and compare it by
guaranteedTPCInstance.getClass().isAssignableFrom(foo())
, while still being kind of hacky, at least is more portable and OOPy IMO.
As to your idea of creating a class in the same package as TheProtectedClass to avoid being package-private - it's a viable solution, but a) it breaks the basic principle of encapsulation and the programming contract of the TPC class; packaging is done by library/class authors for a reason - to prevent irresponsible data access and using private API or undocumented proprietary methods, b) it's not always possible (and shouldn't be possible in case of properly designed library classes), since those classes can be not only package-private, but final or effectively final (anonymous inner classes etc) - for the reasons described by Bloch in EJ 2nd, "favor composition over inheritance" item, see also Good reasons to prohibit inheritance in Java? Use of final class in Java etc c) you can't do it with some Java library classes, as you can't define your class to be and use e.g. java.lang package. As such, the only "portable" solution is through reflection and through what I described.
tl;dr The fact you can piggyback another package by mimicking its package definition is an obvious C-style deficiency of Java's syntax (allowing programmer to do what he shouldn't be able to normally do; same goes with some specific reflection methods); hacks made this way are neither maintainable nor safe.
NOTE: If you you expect to do something in a internal implementation-dependent and, at the same time, portable and maintainable (e.g. impervious to implementation changes/class name changes etc) way, you're obviously expecting the impossible.
It appears that the best solution is to create a package in your project that has the same package as the package-private class and either expose TheProtectedClass.class as a Class<?> or simply add a simple method that checks if your Object is instanceof TheProtectedClass.
This does not require reflection, it is fast and relatively safe (compilation will break if the package-private class changes name).
I am looking for a java equivalent to the C# extension methods feature. Now I have been reading about Java 8's default methods, but as far as I can see, I can only add these to interfaces...
...is there any language feature that will allow me to write an extension method for a final class that doesn't implement an interface? (I'd rather not have to wrap it...)
Java doesn't have extension methods. Default methods are not extension methods. Let's look at each feature.
Default methods
Both Java and C# support this feature
Problems solved:
Many objects may implement the same interface and all of them may use the same implementation for a method. A base class could solve this issue but only if the interface implementors don't already have a base class as neither java nor C# support multiple inheritance.
An API would like to add a method to an interface without breaking the API consumers. Adding a method with a default implementation solves this.
Java's or C#'s default methods are a feature to add a default implementation to an interface. So objects that extend an interface don't have to implement the method, they could just use the default method.
interface IA { default public int AddOne(int i) { return i + 1; } }
Any object that implements IA doesn't have to implement AddOne because there is a default method that would be used.
public class MyClass implements IA { /* No AddOne implementation needed */ }
C# now has this feature in C# 8 (or .Net 5)
C#'s Extension Method
Problems solved:
Ability to add methods to sealed classes.
Ability to add methods to classes from third-party libraries without forcing inheritance.
Ability to add methods to model classes in environments where methods in model classes are not allowed for convention reasons.
The ability for IntelliSense to present these methods to you.
Example: The type string is a sealed class in C#. You cannot inherit from string as it is sealed. But you can add methods you can call from a string.
var a = "mystring";
a.MyExtensionMethed()
Java lacks this feature and would be greatly improved by adding this feature.
Conclusion
There is nothing even similar about Java's default methods and C#'s extension method features. They are completely different and solve completely different problems.
C# extension methods are static and use-site, whereas Java's default methods are virtual and declaration-site.
What I believe you are hoping for is the ability to "monkey-patch" a method into a class you do not control, but Java does not give you that (by design; it was considered and rejected.)
Another benefit of default methods over the C# approach is that they are reflectively discoverable, and in fact from the outside, don't look any different from "regular" interface methods.
One advantage of C#'s extension methods over Java's default methods is that with C#'s reified generics, extension methods are injected into types, not classes, so you can inject a sum() method into List<int>.
Above all, the main philosophical difference between Java's default methods and C#'s extension methods is that C# lets you inject methods into types you do not control (which is surely convenient for developers), whereas Java's extension methods are a first-class part of the API in which they appear (they are declared in the interface, they are reflectively discoverable, etc.) This reflects several design principles; library developers should be able to maintain control of their APIs, and library use should be transparent -- calling method x() on type Y should mean the same thing everywhere.
C# extension methods are just syntactic sugar for static methods that take the extended type as first argument. Java default methods are something completely different. To mimic C# extension methods, just write usual static methods. You will not have the syntatic sugar, however; Java does not have this feature.
Java default methods are real virtual methods. For example, they can be overridden. Consider a class X inheriting from an interface I that declares a default foo() method. If X or any of its super classes declares no own foo() method, then X will get the foo() implementation of I. Now, a subclass Y of X can override X.foo() like a usual method. Thus, default methods are not only syntactic sugar. They are real extensions of the method overriding and inheritance mechanism that cannot be mimicked by other language features.
Default methods even require special VM support, so they are not even a compiler only feature: During class loading, the hierarchy of a class has to be checked to determine which default methods it will inherit. Thus, this decision is made at runtime, not at compile time. The cool thing about it is that you do not have to recompile a class when an interface it inherits gets a new default method: The VM will, at class load time, assign that new method to it.
It is possible to have extension methods with some tricks.
You may give a try to Lombok or XTend. Although extension methods don't come with the out of the box Java implementation, both Lombok and XTend offers a fully working solution.
Lombok is a simple standalone code processing framework, which makes most of the criticized Java specific hassle less painful, including extension methods:
https://projectlombok.org/features/experimental/ExtensionMethod.html
Xtend http://www.eclipse.org/xtend/ goes a few lightyears forward, and implements a language which is a combination of the best parts of modern languages such as Scala on top of Java and Java type system. This allows implementing some classes in Xtend and others in Java within the same project. The Xtend code complies to valid Java code, so no JVM magic happens under the hood. On the other hand, it is a little too much if you have only extension methods missing.
JPropel https://github.com/nicholas22/jpropel-light implements LINQ style extension methods in Java using Lombok. It may worth of a peek :)
In a lecture on Java, a computer science professor states that Java interfaces of a class are prototypes for public methods, plus descriptions of their behaviors.
(Source https://www.youtube.com/watch?v=-c4I3gFYe3w #8:47)
And at 8:13 in the video he says go to discussion section with teaching assistants to learn what he means by prototype.
What does "prototype" mean in Java in the above context?
I think the use of the word prototype in this context is unfortunate, some languages like JavaScript use something called prototypical inheritance which is totally different than what is being discussed in the lecture. I think the word 'contract' would be more appropriate. A Java interface is a language feature that allows the author of a class to declare that any concrete implementations of that class will provide implementations of all methods declared in any interfaces they implement.
It is used to allow Java classes to form several is-a relationships without resorting to multiple inheritance (not allowed in Java). You could have a Car class the inherits from a Vehicle class but implements a Product interface, therefor the Car is both a Vehicle and a Product.
What does "prototype" mean in Java in the above context?
The word "prototype" is not standard Java terminology. It is not used in the JLS, and it is not mentioned in the Java Tutorial Glossary. In short there is no Java specific meaning.
Your lecturer is using this word in a broader sense rather than a Java-specific sense. In fact, his usage matches "function prototype" as described in this Wikipedia page.
Unfortunately, the "IT English" language is full of examples where a word or phrase means different (and sometimes contradictory) things in different contexts. There are other meanings for "template" that you will come across in IT. For instance:
In C++ "template" refers to what Java calls a generic class or method.
In Javascript, an object has a "template" attribute that gives the objects methods.
More generally, template-based typing is an alternative (more dynamic) way of doing OO typing.
But the fact that these meanings exist does not mean that your lecturer was wrong to refer to interface method signatures as "templates".
"prototype" is not the the best/right terminus to be used. interfaces are more like "contracts", that implementing classes have to fulfill.
The method's heads/definitions will have to be implemented in the implementing class (using implements keyword in the class head/class definition/public class xy implements ...).
I guess this naming conventions leave much room for many ideological debates.
Or the author had some sort of a mental lapsus and mapped the construct of prototypical inheritance from javascript into java in his mind somehow.
Interfaces are not prototypes for classes in Java.
In languages like C & C++, which compiles to machine code sirectly, compiler should be aware of the nature of any identifier (variable/class/functions) before they are references anywhere in the program. That mean those languages require to know the nature of the identifier to generate a machine code output that is related to it.
In simple words, C++ compiler should be aware of methods and member of a class before that class is used anywhere in the code. To accomplish that, you should define the class before the code line where it is used, or you should at least declare its nature. Declaring only the nature of a function or a class creates a 'prototype'.
In Java, an 'interface' is something like description of a class. This defines what all methods a particular kind of class should mandatory have. You can then create classes that implements those interface. Main purpose that interfaces serve in java is the possibility that a Variable declared as of a particular interface type can hold objects of any class that implements the object.
He tells it in C/C++ way, let me explain, in C++ you can define prototypes for methods at the header files of classes so that other classes can recognize these methods, also in C where there is no class concept, you can define prototypes at the beginning of file and then at somewhere in same file you can implement these prototypes, so that methods can be used even before their implementation is provided. So in Java interfaces provide pretty much same way, you can define prototypes for methods(method headers) that will be implemented by classes that implement this interface.
In a lecture on Java, a computer science professor states that:
Java interfaces of a class are:
1. are prototypes for public methods,
2. plus descriptions of their behaviors.
For 1. Is ok: - yes, they are prototypes for implemented public methods of a class.
For 2. This part could be a little bit tricky. :)
why?
we know: interface definition (contain prototypes), but doesn't define (describe) methods behavior.
computer science professor states: "... plus descriptions of their behaviors.". This is correct only if we look inside class that implements that interface (interface implementation = prototype definitions or descriptions).
Yes, a little bit tricky to understand :)
Bibliography:
Definition vs Description
Context-dependent
Name visibility - C++ Tutorials
ExtraWork:
Note: not tested, just thinking! :)
C++:
// C++ namespace just with prototypes:
// could be used like interface similar with Java?
// hm, could we then define (describe) prototypes?
// could we then inherit namespace? :)
namespace anIntf{
void politeHello(char *msg);
void bigThankYou();
}
Prototypes provide the signatures of the functions you will use
within your code. They are somewhat optional, if you can order
your code such that you only use functions that are previously
defined then you can get away without defining them
Below a prototype for a function that sums two integers is given.
int add(int a, int b);
I found this question because i have the same impression as that teacher.
In early C (and C++ i think) a function, for example "a" (something around lexic analysis or syntactic, whatever) can not be called, for example inside main, before it's declaration, because the compiler doesn't know it (yet).
The way to solve it was, either to declare it before it's usage (before main in the example), or to create a prototype of it (before main in the example) which just specifies the name, return values and parameters; but not the code of the function itself, leaving this last one for wherever now is placed even after it's called.
These prototypes are basically the contents of the include (.h) files
So I think is a way to understand interfaces or the way they say in java "a contract" which states the "header" but not the real body, in this case of a class or methods
In Java, I define an abstract class with both concrete and abstract methods in it, and it has to be subclassed independently by third-party developers. Just to be sure: are there any changes I could make to the abstract class that are source compatible with their classes but not binary compatible? In other words: after they have compiled their subclasses, could I change the abstract class - apart from e.g. adding an abstract method to it or removing a protected method from it that is called by subclasses, which are of course source incompatible - in a way that could force them to recompile their subclasses?
If it isn't too late to change your system, I would suggest that you do that. Overriding is usually not a good way to customize functionality, as it is incredibly fragile. For example, if you later use a method name that your clients have used (which they are now unintentionally automatically overriding), then it is possible that the override will completely break the invariants of your class. A usually better way of providing customization is to give your clients an interface which is limited to just the customized behavior, and then you have a fully concrete class that depends on an instance of this interface, and delegates appropriately to the interface when it needs to use the customized behaviors. This way, your code and your client's code are completely separated, and they won't interfere with each other.
I am assuming that you are using "binary incompatibility" in the technical sense; e.g. where the classloader detects the incompatibility and refuses to load the classes.
Binary incompatibility could also be introduced if you added a visible method and declared it final, and that method collided with the signature of some existing method in a third-party subclass. However, if the method is non-final, the existing method will turn into an override of your (new) method which might cause problems ... but not binary incompatibility.
Likewise, adding new visible fields will result in hiding, may result in confusing behavior and will break object serialization. But this will not result in binary incompatibility.
In general this points to the fact that you need to consider application semantic issues as well as simple binary compatibility. And the Java type system won't help you there.
For completeness, there are a other things that you could do in your code that would break binary compatibility for the 3rd party classes:
reduce the visibility of your abstract class and/or its methods,
change the signatures of other classes used as parameter result and exception types,
change the chain of superclasses that your abstract class extends, or make an incompatible change in those classes, or
change the tree of interfaces that your abstract class implements, or make an incompatible change in those interfaces.
Sure.
You can accidently use a method name that they've used, which is now suddenly overridden, with perhaps dramatically different results.
You can add fields to the class which mess up serialization etc.