Protect "default" methods from overriding - java

I'm looking for a solution, that allows to protect the default methods from inheritance. The easiest solution could be - extend from class and etc... but in my case it's not possible.
Can someone suggest how to solve this problem? Could there be any workarounds?
Atm I have following code, which needs to be reworked (if/any possible):
public interface MyInterface1 {
default boolean isA(Object obj) {
return (boolean) obj.equals("A") ? true : false;
}
default boolean isB(Object obj) {
return (boolean) obj.equals("B") ? true : false;
}
}
public class MyClass extends MyLogic implements MyInterface, MyInterface1 {
// this class allows to inherit methods from both interfaces,
// but from my perspective i'd like to use the methods from MyInterface1 as it is,
// with a 'protection' from inheritance. is that possible?
}

You seem to want a way to write your interface so that implementing classes cannot provide their own implementations of its default methods. There is no way to do this, and indeed it runs counter to the purpose of interfaces in general and default members in particular.
The point of default methods is to provide a way to add methods to existing interfaces without instantly breaking all their existing implementations. Generally speaking, this is a binary compatibility issue, not a functionality issue. There's no particular reason to suppose in general that default implementations can provide the intended functionality, but without them, even old code that doesn't rely on the new methods at all is incompatible with interface revisions that add methods.
I think you have a factoring issue. Rather than trying to force classes to provide a specific implementation of a specific method -- which cannot even refer to that class's members, except possibly others defined by the same interface -- you should provide the common methods in a class of their own. After all, since you want all classes involved to provide identical implementations, it doesn't matter which class's implementations you actually use. Moreover, there is therefore no particular usefulness in marking any given class as providing implementations of the well-known methods.
Example:
public class MyImplementation1 {
public static boolean isA(Object obj) {
return obj.equals("A");
}
public static isB(Object obj) {
return obj.equals("B");
}
}
// Wherever needed, use as MyImplementation1.isA(o), etc.
You can do this even if you want these pre-baked implementations to operate in terms of the other methods of your interface. In that case, just add an argument to the fixed methods that provides the object to operate on. Perhaps that's what the obj arguments in your example were supposed to be; in that case, this may be closer to what you're after:
public interface MyInterface3 {
public String someInterfaceMethod();
}
public class MyImplementation2 {
public static boolean isA(MyInterface3 subject) {
return subject.someInterfaceMethod().equals("A");
}
public static boolean isB(MyInterface3 subject) {
return subject.someInterfaceMethod().equals("B");
}
}

You can't. At least if you restrict yourself to a pure-java-compiler solution.
And the reason is because it was not designed to do that: the purpose is to add new methods to existing interface (like java.util.Collection) without breaking the implementations. That way, we have sort(), stream(), forEach() on Collection.
If you were to allow such thing (forbidding implementation), then it would means a change in the interface would result in a compilation error for implementation (because they would override the method, method that would been rendered final). That was not the purpose.
There are several other options to achieve that, depending on your need:
Abstract class with final method being the previously default method.
Testing the default behavior using unit testing.
Testing the possible implementation and check they don't override it.
The last case can probably be done easily with Reflections: you would have to list all implementations, and check for each interface's default method that there is no overriding using Reflections.

I take it you mean you want to write a class that uses the default methods of an interface, but does not inherit them.
In your example code, you attempted to use the default methods by implementing the interface. When you implement an interface, by design you also inherit all its methods. This is the Liskov Substitution Principle. By implementing the interface you are telling your users that all instances of your class are substitutable for instances of the interface. But if the interface default methods weren't inherited, this wouldn't be true, so you would be lying to users of your class.
To have your class use the interface's default methods without inheriting them, don't implement the interface! Instead, use a helper class that does:
public interface MyInterface1 {
default boolean isA(Object obj) {
return obj.equals("A"); // or "A".equals(obj) to avoid NullPointerException
}
default boolean isB(Object obj) {
return obj.equals("B");
}
}
public class MyClass extends MyLogic implements MyInterface {
private static class Helper implements MyInterface1 {
void doSomeWork() {
// do something that calls isA() and isB()...
}
}
public void someMethodOfMyClass() {
// ...
Helper.doSomeWork();
// ...
}
}

No, This is not possible due to the way java implements the interface (pun intended). For more information as to the reason for this, see the answers to this question Why is "final" not allowed in Java 8 interface methods?
However here are some other ways to guide a developer not to override a default method:
A source code comment
//Do not inherit please
A javadoc comment

Related

does using default methods in interfaces violates Interface segregation principle?

I'm learning about SOLID principles, and ISP states that:
Clients should not be forced to depend upon interfaces that they do
not use.
Does using default methods in interfaces violate this principle?
I have seen a similar question but I'm posting here with an example to get a clearer picture if my example violate ISP.
Say I have this example:
public interface IUser{
void UserMenu();
String getID();
default void closeSession() {
System.out.println("Client Left");
}
default void readRecords(){
System.out.println("User requested to read records...");
System.out.println("Printing records....");
System.out.println("..............");
}
}
With the following classes implementing IUser Interface
public class Admin implements IUser {
public String getID() {
return "ADMIN";
}
public void handleUser() {
boolean sessionIsOpen = true;
while (sessionIsOpen) {
switch (Integer.parseInt(in.readLine())) {
case 1 -> addNewUser();
case 2 -> sessionIsOpen=false;
default -> System.out.println("Invalid Entry");
}
}
closeSession();
}
private void addNewUser() {
System.out.println("Adding New User..."); }
}
}
Editor Class:
public class Editor implements IUser {
public String getID() {
return "EDITOR";
}
public void handleUser() {
boolean sessionIsOpen=true;
while (sessionIsOpen){
switch (Integer.parseInt(in.readLine())) {
case 1 -> addBook();
case 2 -> readRecords();
case 3 -> sessionIsOpen=false;
default ->
System.out.println("Invalid Entry");
}
}
closeSession();
}
private void addBook() {
System.out.println("Adding New Book..."); }
}
}
Viewer Class
public class Viewer implements IUser {
public String getID() {
return "Viewer";
}
public void handleUser() {
boolean sessionIsOpen=true;
while (sessionIsOpen){
switch (Integer.parseInt(in.readLine())) {
case 1 -> readRecords();
case 2 -> sessionIsOpen=false;
default ->
System.out.println("Invalid Entry");
}
}
closeSession();
}
}
Since editor and viewer class use readRecords() method and Admin class doesn't provide an implementation for that method, I implemented it as a default method in IUser Interface to minimize code repetition (DRY Principle).
Am I violating the interface segregation principle in the above code by using default methods in IUser because the Admin class does not use the read method?
Can someone explain please, because I think I'm not forcing Admin class to use methods/interfaces that they do not use.
does using default methods in interfaces violate the principle?
No, not if they're used correctly. In fact, they can help to avoid violating ISP (see below).
Does your example of using default methods violate ISP?
Yes! Well, probably. We could have a debate about exactly how badly it violates ISP, but it definitely violates a bunch of other principles, and isn't good practice with Java programming.
The problem is that you're using a default method as something for the implementing class to call. That's not their intent.
Default methods should be used to define methods that:
users of the interface will likely wish to call (i.e. not implementers)
provide aggregate functionality
have an implementation that is likely to be the same for most (if not all) implementers of the interface
Your example appears to break several conditions.
The first condition is there for a simple reason: all inheritable methods on Java interfaces are public, so they always can be called by users of the interface. To give a concrete example, the below code works fine:
Admin admin = new Admin();
admin.closeSession();
admin.readRecords();
Presumably, you don't want this to be possible, not just for Admin, but for Editor and Viewer too? I would argue that this is a sort-of violation of ISP, because you are depending on users of your classes not calling those methods. For the Admin class, you could make readRecords() 'safe' by overriding it and giving it a no-op implementation, but that just highlights a much more direct violation of ISP. For all other methods/implementations, including the classes that do make use of readRecords(), you're screwed. Rather than thinking of this in terms of ISP, I'd call it API or implementation leakage: it allows your classes to be used in ways that you didn't intend (and may wish to break in the future).
The second condition I stated might need further explanation. By aggregate functionality, I mean that the methods should probably call (either directly or indirectly) one or more of the abstract methods on the interface. If they don't do that, then the behaviour of those methods can't possibly depend on the state of the implementing class, and so could probably be static, or moved into a different class entirely (i.e. see the Single-responsibility principle). There are examples and use cases where it's OK to relax this condition but they should be thought about very carefully. In the example you give, the default methods are not aggregate, but it looks like sanitized code for the sake of Stack Overflow, so maybe your "real" code is fine.
It's debatable whether 2/3 implementers counts as "most" with with regards to my third condition. However, another way to think about it is you should know in advance of writing the implementing classes whether or not they should have that method with that functionality. How certainly can you say whether in the future, if you need to create a new class of User, they will require the functionality of readRecords()? Either way, it's a moot point as this condition only really needs to be thought about if you haven't violated the first 2.
A good use of default methods
There are examples in the standard library of good uses default methods. One would be java.util.function.Function with its andThen(...) and compose(...) methods. These are are useful pieces of functionality for users of Functions, they (indirectly) make use of the Function's abstract apply(...) method, and importantly, it's highly unlikely that an implementing class would ever wish to override them, except maybe for efficiency in some highly specialized scenarios.
These default methods do not violate ISP, as classes that implement Function have no need to call or override them. There may be many use-cases where concrete instances of Function never have their andThen(...) method called, but that's fine – you don't break ISP by providing useful but non-essential functionality, as long as you don't encumber all those use-cases by forcing them to do something with it. In the case of Function, providing these methods as abstract rather than default would violate ISP, as all implementing classes would have to add their own implementations, even when they know it's unlikely to ever be called.
How can you achieve DRY without breaking 'the rules'?
Use an abstract class!
Abstract classes have been poo-pooed a lot in discussions about good Java practice, because they were frequently misunderstood, misued and abused. It wouldn't surprise me if at least some programming best-practice guides like SOLID were published in reaction to this misuse. A very frequent issue I've seen is having an abstract class provide a "default" implementation for tons of methods that is then overridden almost everywhere, often by copy-pasting the base implementation and changing 1 or 2 lines. Essentially, this is breaking my third condition on default methods above (which also applies to any method on an intended-to-be-subclassed type), and it happens A LOT.
However, in this scenario, abstract classes are probably just what you need.
Something like this:
interface IUser {
// Add all methods here intended to be CALLED by code that holds
// instances of IUser
// e.g.:
void handleUser();
String getID();
// If some methods only make sense for particular types of user,
// they shouldn't be added.
// e.g.:
// NOT void addBook();
// NOT void addNewUser();
}
abstract class AbstractUser implements IUser {
// Add methods and fields here that will be USEFUL to most or
// all implementations of IUser.
//
// Nothing should be public, unless it's an implementation of
// one of the abstract methods defined on IUser.
//
// e.g.:
protected void closeSession() { /* etc... */ }
}
abstract class AbstractRecordReadingUser extends AbstractUser {
// Add methods here that are only USEFUL to a subset of
// implementations of IUser.
//
// e.g.:
protected void readRecords(){ /* etc... */ }
}
final class Admin extends AbstractUser {
#Override
public void handleUser() {
// etc...
closeSession();
}
public void addNewUser() { /* etc... */ }
}
final class Editor extends AbstractRecordReadingUser {
#Override
public void handleUser() {
// etc...
readRecords();
// etc...
closeSession();
}
public void addBook() { /* etc... */ }
}
final class Viewer extends AbstractRecordReadingUser {
#Override
public void handleUser() {
// etc...
readRecords();
// etc...
closeSession();
}
}
Note: Depending on your situation, there may be better alternatives to abstract classes that still achieve DRY:
If your common helper methods are stateless (i.e. don't depend on fields in the class), you could use an auxiliary class of static helper methods instead (see here for an example).
You might wish to use composition instead of abstract class inheritance. For example, instead of creating the AbstractRecordReadingUser as above, you could have:
final class RecordReader {
// Fields relevant to the readRecords() method
public void readRecords() { /* etc... */ }
}
final class Editor extends AbstractUser {
private final RecordReader r = new RecordReader();
#Override
void handleUser() {
// etc...
r.readRecords();
// etc...
}
}
// Similar for Viewer
This avoids the problem that Java doesn't allow multiple inheritance, which would become an issue if you tried to have multiple abstract classes containing different pieces of optional functionality, and some final classes needed to use several of them. However, depending on what state (i.e. fields) the readRecord() method needs to interact with, it might not be possible to separate it out into a separate class cleanly.
You could just put your readRecords() method in AbstractUser and avoid having the additional abstract class. The Admin class isn't obliged to call it, and as long as the method is protected, there's no risk that anyone else will call it (assuming you have your packages properly separated). This doesn't violate ISP as even though Admin can interact with readRecords(), it isn't forced to. It can pretend that method doesn't exist, and everyone is fine!
I believe this is a violation of the principle ISP. But you don't have to strictly follow all solid principles as this will complicate development.

Using default keyword in interface correctly

I have a co worker who need a method to be available to two classes.
He decided to create a new interface to be implemented by those classes.
The interface has one method
default doThis(String parameter)
It does not have any other interface methods, there is no indication that other methods would be added to this interface.
I feel this is an incorrect usage of the interface and it should be done in a different way. I.e perhaps a class which has the method allowing other classes to consume this by using the object.
Does anyone with experience on this have any opinions to share?
I can update with more clarification based on your comments.
Update:
Here is the code and the question remains:
is this a valid use of the default method or should this common logic have been done in another way like a Utilities class which does the saving to preferences ?
Interface:
public interface LogInCookie {
default void mapCookiesToPreferences(String cookie) {
if (cookie.contains(MiscConstants.HEADER_KEY_REFRESH)) {
String refreshToken = cookie.replace(MiscConstants.HEADER_KEY_REFRESH, StringUtils.EMPTY);
SharedPrefUtils.addPreference(SharedPrefConstants.REFRESH_TOKEN, refreshToken);
}
}
}
public class HDAccountActivity extends AbstractActivity implements LogInCookie {
private void mapCookies(List<String> mValue) {
LogInCookie.super.mapCookiesToPreferences(mValue); //ekh!
}
}
public class BaseSplashPage extends AppCompatActivity implements DialogClickedCallBack, LogInCookie {
//method which uses this
private void mapCookiesToPreferences(List<String> headers) {
int firstItemInHeader = 0;
for (String header : headers) {
String mValue = header.substring(firstItemInHeader,header.indexOf(MiscConstants.SEMICOLON));
LogInCookie.super.mapCookiesToPreferences(mValue); //ekh!
}
}
}
A default method in an interface, which doesn’t define other methods, can’t do much useful things with the instance of the implementing class. It can only use methods inherited from java.lang.Object, which are unlikely to carry semantics associated with the interface.
If the code doesn’t use instance methods on this at all, in other words, is entirely independent from the this instance, you should make it static, change the containing class to a non-instantiable class type, i.e.
final class SomeUtilClass {
static void doThis(String parameter) {
// ...
}
private SomeUtilClass() {} //no instances
}
and use import static packageof.SomeUtilClass.doThis; in the classes using this method.
That way, all these classes can invoke the method like doThis(…) without a qualifying type name, without needing a misleading type hierarchy.
When the method actually uses the this instance, which, as said, can only be in terms of methods inherited from java.lang.Object, the type inheritance might be justified. Since this is rather unlikely, you might still consider the type hierarchy to be misleading and rewrite the code to
final class SomeUtilClass {
static void doThis(Object firstParameter, String parameter) {
// ...
}
private SomeUtilClass() {} //no instances
}
using firstParameter instead of this, which can be invoke like doThis(this, …).
Ideally you would put that method doThis() in an abstract class that both classes extend. However if you need to achieve multiple inheritance then using an interface here is fine.
A class with a static method doThis() that you can call staticly would also work.
It all depends on how you have your project organized imo.
In java 8 , default keyword in interface was introduced for those cases where if any set of apis had long inheritance hierarchy and we wanted to introduce a method that should be available in all of the lower lying classes.
So for ex. in Java 8 stream() method was introduced in the Collection interface as a default method and it ended up being available in all of the underlying classes.
As far as your case in considered , if I go by your words then if yours is a new development then you should be using interface -> abstract class -> actual implementing class.
Only if yours was an older development setup and you already had classes implementing from an interface , that could have been an ideal scenario for using default method in your interface.
A default method in an interface
*)can have a default implementation
*)which can overridden by the implementing class
yes its a correct usage since JAVA8.
we can have default method in an interface as well as a abstract method

Why does Java not allow multiple inheritance but does allow conforming to multiple interfaces with default implementations

I am not asking this -> Why is there no multiple inheritance in Java, but implementing multiple interfaces is allowed?
In Java, multiple inheritance isn't allowed, but, after Java 8, Interfaces can have default methods (can implement methods itself), just like abstract classes. Within this context, it multiple inheritance should also be allowed.
interface TestInterface
{
// abstract method
public void square(int a);
// default method
default void show()
{
System.out.println("Default Method Executed");
}
}
Things are not so simple.
If a class implements multiple interfaces that defines default methods with the same signature the compiler will force you to override this method for the class.
For example with these two interfaces :
public interface Foo {
default void doThat() {
// ...
}
}
public interface Bar {
default void doThat() {
// ...
}
}
It will not compile :
public class FooBar implements Foo, Bar{
}
You should define/override the method to remove the ambiguity.
You could for example delegate to the Bar implementation such as :
public class FooBar implements Foo, Bar{
#Override
public void doThat() {
Bar.super.doThat();
}
}
or delegate to the Foo implementation such as : :
public class FooBar implements Foo, Bar {
#Override
public void doThat() {
Foo.super.doThat();
}
}
or still define another behavior :
public class FooBar implements Foo, Bar {
#Override
public void doThat() {
// ...
}
}
That constraint shows that Java doesn't allow multiple inheritancy even for interface default methods.
I think that we cannot apply the same logic for multiple inheritances because multiples issues could occur which the main are :
overriding/removing the ambiguity for a method in both inherited classes could introduce side effects and change the overall behavior of the inherited classes if they rely on this method internally. With default interfaces this risk is also around but it should be much less rare since default methods are not designed to introduce complex processings such as multiple internal invocations inside the class or to be stateful (indeed interfaces cannot host instance field).
how to inherit multiple fields ? And even if the language allowed it you would have exactly the same issue as this previously quoted : side effect in the behavior of the inherited class : a int foo field defined in a A and B class that you want to subclass doesn't have the same meaning and intention.
The language designers already thought about that, so these things are enforced by the compiler. So if you define:
interface First {
default void go() {
}
}
interface Second {
default void go() {
}
}
And you implement a class for both interfaces:
static class Impl implements First, Second {
}
you will get a compilation error; and you would need to override go to not create the ambiguity around it.
But you could be thinking that you can trick the compiler here, by doing:
interface First {
public default void go() {
}
}
static abstract class Second {
abstract void go();
}
static class Impl extends Second implements First {
}
You could think that First::go already provides an implementation for Second::go and it should be fine. This is too taken care of, thus this does not compile either.
JLS 9.4.1.3 : Similarly, when an abstract and a default method with matching signatures are inherited, we produce an error. In this case, it would be possible to give priority to one or the other - perhaps we would assume that the default method provides a reasonable implementation for the abstract method, too. But this is risky, since other than the coincidental name and signature, we have no reason to believe that the default method behaves consistently with the abstract method's contract - the default method may not have even existed when the subinterface was originally developed. It is safer in this situation to ask the user to actively assert that the default implementation is appropriate (via an overriding declaration).
The last point I would bring in, to solidify that multiple inheritance is not allowed even with new additions in java, is that static methods from interfaces are not inherited. static methods are inherited by default:
static class Bug {
static void printIt() {
System.out.println("Bug...");
}
}
static class Spectre extends Bug {
static void test() {
printIt(); // this will work just fine
}
}
But if we change that for an interface (and you can implement multiple interfaces, unlike classes):
interface Bug {
static void printIt() {
System.out.println("Bug...");
}
}
static class Spectre implements Bug {
static void test() {
printIt(); // this will not compile
}
}
Now, this is prohibited by the compiler and JLS too:
JLS 8.4.8 : A class does not inherit static methods from its superinterfaces.
Java doesn't allow multiple inheritance for fields. This would be difficult to support in the JVM as you can only have references to the start of an object where the header is, not arbitrary memory locations.
In Oracle/Openjdk, objects have a header followed by the fields of the most super class, then the next most super class, etc. It would be a significant change to allow the fields of a class to appear at different offsets relative to the header of an object for different subclasses. Most likely object references would have to become a reference to the object header and a reference to the fields to support this.
default methods in interfaces pose a problem that :
If both of the implemented interfaces define a default method with
same method signature, then the implementation class does not know
which default method to use.
The implementation class should define explicitly specify which default method to use or define it's own one.
Thus default methods in Java-8 do not facilitate multiple inheritance. The main motivation behind default methods is that if at some point we need to add a method to an existing interface, we can add a method without changing the existing implementation classes. In this way, the interface is still compatible with older versions. However, we should remember the motivation of using Default Methods and should keep the separation of interface and implementation.
The main issues with multiple inheritance are ordering (for overriding and calls to super), fields and constructors; interfaces don't have fields or constructors, so they don't cause problems.
If you look at other languages they usually fall in two broad categories:
Languages with multiple inheritance plus a few features to disambiguate special cases: virtual inheritance [C++], direct calls to all superconstructors in the most-derived class [C++], linearization of superclasses [Python], complex rules for super [Python], etc.
Languages with a differente concept, usually called interfaces, traits, mixins, modules, etc. that impose some limitations such as: no constructors [Java] or no constructors with parameters [Scala until very recently], no mutable fields [Java], specific rules for overriding (e.g. mixins take precedence over base classes [Ruby] so you can include them when you need a bunch of utility methods), etc. Java has become a language like these.
Why just by disallowing fields and constructors you solve many issues related to multiple inheritance?
You can't have duplicated fields in duplicated base classes.
The main class hierarchy is still linear.
You can't construct your base objects the wrong way.
Imagine if Object had public/protected fields and all subclasses had constructors setting those fields. When you inherit from more than one class (all of them derived from Object), which one gets to set the fields? The last class? They become siblings in the hierarchy, so they know nothing about each other. Should you have multiple copies of Object to avoid this? Would all classes interoperate correctly?
Remember that fields in Java are not virtual (overridable), they are simply data storage.
You could make a language where fields behave like methods and could be overridden (the actual storage would be always private), but that would be a much bigger change and problably wouldn't be called Java anymore.
Interfaces can't be instantiated by themselves.
You should always combine them with a concrete class. That eliminates the need for constructors and makes the programmer's intent clearer too (that is, what is meant to be a concrete class and what's an accessory interface/mixin). This also provides a well-defined place to solve all ambiguities: the concrete class.
That is mostly related to "diamonds problem" i think. Right now if you implement multiple interfaces with the same method, compiler forces you to override method the one you want to implement, because it don't know which on to use. I guess Java creators wanted to remove this problem back when interfaces couldn't use default methods. Now they came up with idea, that is good to be able to have methods with implementation in interfaces, as you can still use those as functional interfaces in streams / lambda expressions and utilize their default methods in processing. You cannot do that with classes but diamond problem still exist there. That is my guess :)
class A{
void m1(){
System.out.println("m1-A");
}
}
class B{
void m1(){
System.out.println("m1-B");
}
}
class C extends A, B{ // this will give an error
// inheritance means making all variables and/or methods available to the child class, here child class will get confused as which m1() method to inherit, hence an error
}
JAVA DOES SUPPORT MULTIPLE INHERITANCE.
If you make a OVERALL COMPARISON OF THE PROGRAMMING LANGUAGE,JAVA,THEN YOU COME TO KNOW THAT I AM TRUE.
Java's topclass or the root class in the Ancestor Hierarchy is the Object class.
This class is a Superclass of all other classes. Hence, each class in Java that we declare or is predefined in the API itself inherits this Object class.
Moreover, Java provides us to inherit one more class of our choice.
Hence, we can say that we are performing INTERLOCKED BUT MULTIPLE INHERITANCE.
2ND Way
Java supports Multiple Inheritance of Interfaces. So you can use as many interface implementations you want. But note, implementing an interface does not define IS A relationship as in case of Inheritance of Classes is possible.

Java: Protected Method Before Interface

I have to design a datastructure that'll get implemented multiple times, and I've struck upon a problem.
Since my datastructure needs to have multiple versions of it, I've created an abstract class that lays the groundwork for all implementations. However, the datastructure requires a set-view of certain parts too.
The problem becomes as follows: The set needs to have different implementations depending on the implementation of my datastructure: Either the HashSet or the Collections.SingletonSet. The two implementing datastructures will then extend bits of these to do additional tasks when items are added or removed from the set. However, the abstract datastructure also requires a way to internally remove elements from this set such that this extra work isn't done. For this I'd like to add a protected method to the set, but I can't!
To illustrate, here's some sample code relating to the type of datastructure I'm creating:
public abstract class AbstractEdge {
public abstract AbstractSetView destination(); //Gives a subclass of AbstractSetView in implementations.
public void doStuff() {
destination().removeInternal(foo);
}
public abstract class AbstractSetView implements Set<Vertex> {
protected abstract void removeInternal(Vertex vert);
}
}
public class Edge extends AbstractEdge {
public SetView destination() {
return new SetView();
}
public class SetView extends AbstractSetView,Collections.SingletonSet<Vertex> { //Doesn't work this way.
protected void removeInternal(Vertex vert) {
//Do stuff.
}
}
}
public class HyperEdge extends AbstractEdge {
public SetView destination() {
return new SetView();
}
public class SetView extends AbstractSetView,HashSet<Vertex> { //Doesn't work this way.
protected void removeInternal(Vertex vert) {
//Do stuff.
}
}
}
These are the options I've considered:
As above, extending from multiple classes isn't allowed.
Making the AbstractSetView an interface causes the removeInternal() method to become public, which is undesirable.
Making SetView extend only AbstractSetView and implement everything myself... twice. But this requires me to basically include HashSet and SingletonSet implementations, as an inner class, which is extremely ugly.
Surely the designers of Java made some way around this, to enable me to use their built-in Set implementations? What am I overlooking?
No, they did not "make some way around this" because they didn't see any obstacle, problem, or limitation. According to them, multiple inheritance was not really needed in the language because at least 85% of the time it is used when what really corresponds is composition. 14% of the remaining cases can be solved through interfaces and non-natural use of composition, and 1% with code replication. True: the later is U.G.L.Y. and R.E.D.U.N.D.A.N.T. and U.N.S.A.F.E., etc, but the main objective was to create a small language that could be implemented even in embedded devices. They were not going to give this up for just 1% of the cases. IMHO, they were about right in the percentages.
To answer your second question: don't inherit, especially from library classes, when what you really need is composition. Make AbstractEdge have a member protected Set backingSet; which is initialized with different Set implementations by the subclasses. This is implies that you don't need AbstractSetView and its subclasses.
Otherwise, member protected Set backingSet; can be located in AbstractSetView.
The two answers given so far both offer a solution and advice for the Set case. However, a pattern you can use in this and other similar situations (for example, you are not extending a JRE class, but your own stuff) is to split the interface in a public and an inner protected one.
Your public interface, in this case, will be Set.
Your protected inner interface will be InternalSet, declared inside AbstractEdge, defining the removeInternal method. The method will be "public", but the interface does not need to be.
Then, the abstract super class should define a public method returning the public interface for use outside your subclasses, and a protected one returning the protected interface for internal use only.
Implementing subclasses can then implement a class, extending whatever Set you need, and also implementing the protected class, and return an instance of it from both methods.
The choice between composition or inheriting from JRE classes is all yours.

#MustOverride annotation?

In .NET, one can specify a "mustoverride" attribute to a method in a particular superclass to ensure that subclasses override that particular method.
I was wondering whether anybody has a custom java annotation that could achieve the same effect. Essentially what i want is to push for subclasses to override a method in a superclass that itself has some logic that must be run-through. I dont want to use abstract methods or interfaces, because i want some common functionality to be run in the super method, but more-or-less produce a compiler warning/error denoting that derivative classes should override a given method.
I don't quite see why you would not want to use abstract modifier -- this is intended for forcing implementation by sub-class, and only need to be used for some methods, not all. Or maybe you are thinking of C++ style "pure abstract" classes?
But one other thing that many Java developers are not aware of is that it is also possible to override non-abstract methods and declare them abstract; like:
public abstract String toString(); // force re-definition
so that even though java.lang.Object already defines an implementation, you can force sub-classes to define it again.
Ignoring abstract methods, there is no such facility in Java. Perhaps its possible to create a compile-time annotation to force that behaviour (and I'm not convinced it is) but that's it.
The real kicker is "override a method in a superclass that itself has some logic that must be run through". If you override a method, the superclass's method won't be called unless you explicitly call it.
In these sort of situations I've tended to do something like:
abstract public class Worker implements Runnable {
#Override
public final void run() {
beforeWork();
doWork();
afterWork();
}
protected void beforeWork() { }
protected void afterWork() { }
abstract protected void doWork();
}
to force a particular logic structure over an interface's method. You could use this, for example, to count invocations without having to worry about whether the user calls super.run(), etc.
... and if declaring a base class abstract is not an option you can always throw an UnsupportedOperationException
class BaseClass {
void mustOverride() {
throw new UnsupportedOperationException("Must implement");
}
}
But this is not a compile-time check of course...
I'm not sure which attribute you're thinking about in .NET.
In VB you can apply the MustOverride modifier to a method, but that's just the equivalent to making the method abstract in Java. You don't need an attribute/annotation, as the concept is built into the languages. It's more than just applying metadata - there's also the crucial difference that an abstract method doesn't include any implementation itself.
If you do think there's such an attribute, please could you say which one you mean?
Android has a new annotation out as announced in the Google I/O 2015:
#callSuper
More details here:
http://tools.android.com/tech-docs/support-annotations
If you need some default behaviour, but for some reason it should not be used by specializations, like a implementation of a logic in a non abstract Adapter class just for easy of prototyping but which should not be used in production for instance, you could encapsulate that logic and log a warning that it is being used, without actually having to run it.
The base class constructor could check if the variable holding the logic points to the default one. (writing in very abstract terms as I think it should work on any language)
It would be something like this (uncompiled, untested and incomplete) Java (up to 7) example:
public interface SomeLogic {
void execute();
}
public class BaseClass {
//...private stuff and the logging framework of your preference...
private static final SomeLogic MUST_OVERRIDE = new SomeLogic() {
public void execute() {
//do some default naive stuff
}
};
protected SomeLogic getLogic() { return MUST_OVERRIDE; }
//the method that probably would be marked as MustOverride if the option existed in the language, maybe with another name as this exists in VB but with the same objective as the abstract keyword in Java
public void executeLogic() {
getLogic().execute();
}
public BaseClass() {
if (getLogic() == MUST_OVERRIDE) {
log.warn("Using default logic for the important SomeLogic.execute method, but it is not intended for production. Please override the getLogic to return a proper implementation ASAP");
}
}
}
public GoodSpecialization extends BaseClass {
public SomeLogic getLogic() {
//returns a proper implementation to do whatever was specified for the execute method
}
//do some other specialized stuff...
}
public BadSpecialization extends BaseClass {
//do lots of specialized stuff but doesn't override getLogic...
}
Some things could be different depending on the requirements, and clearly simpler, especially for languages with lambda expressions, but the basic idea would be the same.
Without the thing built in, there is always some way to emulate it, in this example you would get a runtime warning in a log file with a home-made-pattern-like-solution, that only your needs should point if it is enough or a more hardcore bytecode manipulation, ide plugin development or whatever wizardry is needed.
I've been thinking about this.
While I don't know of any way to require it with a compile error, you might try writing a custom PMD rule to raise a red-flag if your forgot to override.
There are already loads of PMD rules that do things like reminding you to implement HhashCode if you choose to override equals. Perhaps something could be done like that.
I've never done this before, so I'm not the one to write a tutorial, but a good place to start would be this link http://techtraits.com/programming/2011/11/05/custom-pmd-rules-using-xpath/ In this example, he basically creates a little warning if you decide to use a wildcard in an import package. Use it as a starting point to explore how PMD can analyze your source code, visit each member of a hierarchy, and identify where you forgot to implement a specific method.
Annotations are also a possibility, but you'd have to figure out your own way to implement the navigation through the class path. I believe PMD already handles this. Additionally, PMD has some really good integration with IDEs.
https://pmd.github.io/

Categories

Resources