Issues with method overriding and generics in Java - java

I've been fighting with trying to override a method in a generic abstract class.
public abstract class Grandparent<T extends Grandparent>
public T set(final T other) //does stuff I don't want to do
public abstract class Parent<T extends Parent<T>> extends Grandparent<T>
public T set(final Parent<?> other) // does stuff I want to do
All the child classes extend Parent<child>.
However, I can't call the set() function I want by just constructing one of the child classes.
Child_1 test = new Child_1();
Child_1 test_2 = new Child_1();
test.set(test_2) //this calls the function I don't want
Parent<Child_1> test_3 = new Child_1();
Parent<Child_1> test_4 = new Child_1();
test3.set(test_4) //this calls the function I do want
This requires modification of already-existing code, however. A lot of it. I don't want to rewrite the set method to
public T set(T other)
because then I'll lose the ability to set one child class object from a different child class object.
How can I write the set() method to trigger any time a child object calls it, passing in any other child object, without any modifications to outside code?

To override a method, you need provide an override-equivalent signature, which implies that the method name and number and types of arguments must be equal. This is not the case For Grandparent.set() and Parent.set(). Consequently, Parent.set() overloads, rather than overrides, Grandparent.set().
The simplest solution I see is to generalize the method signatures as follows:
public abstract class Grandparent<T extends Grandparent>
public T set(Grandparent<?> other)
public abstract class Parent<T extends Parent<T>> extends Grandparent<T>
public T set(Grandparent<?> other)
That way, the methods override, and you don't have to modify any child classes.

Subsequent comments helped to clarify what you are after, but I may still be baffled. Perhaps this will help; if not, please try to elaborate on your question.
public abstract class Grandparent<T extends Grandparent<T, Q>, Q extends Grandparent<T, Q>>
{
public abstract Q set(Q other);
}
class Parent<T extends Parent<T>>
extends Grandparent<T, Parent<T>>
{
#Override
public Parent<T> set(Parent<T> other)
{
throw new UnsupportedOperationException("set");
}
}

How can I write the set() method to
trigger any time a child object calls
it, passing in any other child object,
without any modifications to outside
code?
Can you include code modeling what you want to do - I just want to be clear what it is you want because at the moment I suspect it simply is not allowed - no matter what you do.
EDIT
Classes I used to test with...
package test.stack.overflow;
public abstract class GrandParent<T extends GrandParent>
{
public T set(final GrandParent<?> other)
{
System.out.println("GrandParent.set=" + other);
return null;
}
}
public abstract class Parent<T extends Parent<T>> extends GrandParent<T>
{
public Parent<?> set(final Parent<?> other)
{
System.out.println("Parent.set=" + other);
return other;
}
}
public class Child_1 extends Parent<Child_1>
{
}
public class Child_2 extends Parent<Child_2>
{
}
public class TestPeerage
{
public static void main(String[] args)
{
Child_1 c1 = new Child_1();
c1.set(new Child_2());
c1.set(new Child_1());
Parent<Child_1> pc1 = new Child_1();
pc1.set(new Child_2());
pc1.set(new Child_1());
}
}

Related

reuse same class in different class hierarchies

Sometimes your callback interface has more than one callback method, each for different kind of event. One example is org.xml.sax.ContentHandler which has startElement(), characters(), etc.
Sometimes you want to have a set of reusable handlers and chain them in arbitrary order. In Java it's solved by the delegate design pattern: you create an abstract class that implements each method of the interface, see:
javax.xml.stream.util.StreamReaderDelegate
org.xml.sax.helpers.XMLFilterImpl
com.common.util.xml.DelegatingContentHandler
Then you extend this abstract class overriding only the needed methods, then in runtime you create the chain of handlers passing the next delegate to the constructor of the previous delegate.
I was wondering if declare parents of AspectJ would allow to create such chains statically. I don't want to manually create a delegator class for an interface and I don't want to create the chains in runtime.
Here's what I've done so far: there are 3 classes: A,B,C that print their name and then call super. For each possible pair I'd like to create classes: AB,AC,BC that have the features their pair of classes.
The desired output of my program:
ASupport
BSupport
===============
BSupport
CSupport
===============
ASupport
CSupport
===============
The program that doesn't compile:
package org.foo;
public class AnAspect {
public static void main(String[] args) {
new AB().handle(null);
new BC().handle(null);
new AC().handle(null);
}
}
aspect AnAspect1 {
declare parents : AB extends ASupport;
// can only insert a class into hierarchy, but org.foo.BSupport is not a subtype of org.foo.CSupport
declare parents : ASupport extends BSupport;
}
aspect AnAspect2 {
declare parents : BC extends BSupport;
declare parents : BSupport extends CSupport;
}
aspect AnAspect3 {
declare parents : AC extends ASupport;
declare parents : ASupport extends CSupport;
}
class BC extends MyCallback {
}
class AC extends MyCallback {
}
class AB extends MyCallback {
}
class ASupport extends MyCallback {
#Override
public void handle(Object o) {
System.out.println("ASupport");
super.handle(o);
}
}
class BSupport extends MyCallback {
#Override
public void handle(Object o) {
System.out.println("BSupport");
super.handle(o);
}
}
class CSupport extends MyCallback {
#Override
public void handle(Object o) {
System.out.println("CSupport");
super.handle(o);
}
}
abstract class MyCallback {
public void handle(Object o) {
System.out.println("===============");
}
}
Of course you cannot overcome JVM limitations via AspectJ and make ASupport extend both BSupport and CSupport. Each class must have single superclass (or none, in which case it implicitly inherits from Object). Also the variant declare parents : CSupport extends ASupport; would not work because it would lead to a circular hierachy, which is of course forbidden because it makes no logical sense.
You also seem to misunderstand how a delegator pattern works:
It does not work via inheritance and super() calls but
by means of an internal member pointing to the delegate (if any, the first member in the chain does not have a delegate, of course).
Let us just take a look at two of the classes you mentioned in your question, shall we?
package javax.xml.stream.util;
// (...)
public class StreamReaderDelegate implements XMLStreamReader {
private XMLStreamReader reader;
/**
* Construct an empty filter with no parent.
*/
public StreamReaderDelegate(){}
/**
* Construct an filter with the specified parent.
* #param reader the parent
*/
public StreamReaderDelegate(XMLStreamReader reader) {
this.reader = reader;
}
// (...)
}
package org.xml.sax.helpers;
// (...)
public class XMLFilterImpl
implements XMLFilter, EntityResolver, DTDHandler, ContentHandler, ErrorHandler
{
private XMLReader parent = null;
/**
* Construct an empty XML filter, with no parent.
* (...)
*/
public XMLFilterImpl() {
super();
}
/**
* Construct an XML filter with the specified parent.
* (...)
*/
public XMLFilterImpl(XMLReader parent) {
super();
setParent(parent);
}
/**
* Set the parent reader.
* (...)
*/
public void setParent(XMLReader parent) {
this.parent = parent;
}
// (...)
}
See? In both cases there is no inheritance but delegation. The super() calls are unrelated to the delegation pattern, they just make sure that the super class constructor is called as it should be. What we have here is just a flexible list of objects, each one pointing to its delegate, similar to a linked list. This is a much more flexible approach than your idea to cast everything into a fixed set of classes.
IMO your approach is trying to solve a problem which does not really exist. It is an example of the XY problem. Feel free ask follow-up questions if I can help you any further with this. Tell me what you want to achieve and not how you believe it should be done.

Is there a way in Java to call different child method depending on which subclass is the object?

In my project I have a superclass and two subclasses extending from it. There is a method in the superclass that is overriden differently in each subclass.
I want to know if it's possible to introduce a method (in another class) that takes object of either subclass as a parameter and calls a method overriden in one of subclasses (depending on to which subclass does the object belong).
public class Superclass{
public int method(){return 0;}
}
public class Subclass1 extends Superclass{
public int method(){return 1;}
}
public class Subclass2 extends Superclass{
public int method(){return 2;}
}
public class CallingClass{
public static int dependantCall(Superclass parameter){return parameter.method}
I want to be able to do something like
Subclass1 subclassObject = new Subclass1;
System.out.println(CallingClass.dependantCall(subclassObject));
and get output
1
That is what Polymorphism is for! Defining the Superclass as a parameter type will allow you to pass either subclass in.
For example in your other class you can define it like this:
// classes Dog and Cat extend Animal and override makeNoise()
class Owner{
playWith(Animal a){
a.makeNoise();
}
}
Now the Owner can accept owner.makeNoise(cat) and owner.makeNoise(dog)
More reading: https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html
Yes, it is entirely possible. Here's how that method would look like:
public <T extends Superclass> void foo(T subclassObject) {
...
}
Or:
public void foo(Superclass obj) {
...
}
Note that in the above method, you can pass subclasses' objects as well (they are covariant data types).
This is what Java does by default when you create subclases, so no need to do anything special. Each object carries it's type information at run time, and the method invoked would always be the most specific one for the object. Example:
public class Doer {
public void doSomething() {
// Body presence
};
}
public class Painter extends Doer {
#Override
public void doSomething() {
// Paint here
}
}
public class Manager extends Doer {
#Override
public void doSomething() {
// Micromanage here
}
}
// Elsewhere in your code:
public void busyness(Doer doer) {
doer.doSomething();
}
A style note: if it is possible, one should prefer using interfaces instead of base classes (base classes those should be used only if you want to share implementation between subclasses). Example with interfaces:
public interface Doer {
void doSomething();
}
public class JackOfAllTrades implements Does {
#Override
public void doSomething() {
// Do whatever necessary
}
}
// Client code stays exactly the same as above:
public void busyness(Doer doer) {
doer.doSomething();
}
Note that in Java a class can have only one base class but can implement multiple interfaces.
#Override annotations are not strictly required, but they help Java compiler to spot some errors for you (e.g. if you misprint method name).
In your example it would look like
public class CallingClass {
public static int dependantCall(Superclass parameter) {
return parameter.method();
}
}
Subclass1 subclassObject = new Subclass1();
System.out.println(CallingClass.dependantCall(subclassObject));

Dynamic return type of implementation declared in abstract method

I am looking for a way to have, in an abstract method, the return type to be the one of the implementation calling the method.
In other terms, I would like to write something like that:
public class GenericClass {
public <T extends GenericClass> T returnMyself() {
return (T)this; // Compiler warning, unsafe cast
}
}
public class Implem1 extends GenericClass {}
public class Implem2 extends GenericClass {}
public class Main {
public static void main(String[] args) {
Implem1 implem1 = new Implem1();
Implem1 again1 = implem1.returnMyself(); // Works fine, the type is inferred by the type of again1, I think
Implem1 again2 = implem1.<Implem1>returnMyself(); // Works fine, the type is explicitly asked by <Implem1>
Implem2 again3 = implem1.returnMyself(); // Works fine while it shouldn't.
}
}
What I am looking for is a way to declare the method so that at compilation time, returnMyself() can only return the type of the implementation invoking it (in my example, implem1 is of type Implem1), and ensure the code invoking cannot mistake/mix the types.
I searched quite a lot but couldn't find my answer anywhere (some topics seem similar but want a more general case, not explicitly the type of the implementaion invoking the method).
Some answers were correct, but always implied to override the method in each Implementation class, which may be cumbersome and bug-prone on my side. I'm ideally looking for a method that i would have to write only once in the Abstract class.
Any help/answer appreciated :D
You can do it like this:
public class Parent {
public Parent returnMyself() {
return this;
}
}
public class Child extends Parent {
public Child returnMyself() {
return this;
}
}
This is no problem because if you store a Child instance in a Parent variable then you expect a Parent return type of returnMyself(). Even if it is actually a Child object, the Child returned by returnMyself() extends Parent so there you go.
Since you mention abstract in your problem description, how about follow a model similar to Java's Enum class, where the generic type is in the class definition?
public abstract class GenericClass<T extends GenericClass> {
public abstract T returnMyself();
}
public class Implem1 extends GenericClass<Implem1> {
#Override
public Implem1 returnMyself() {
return this;
}
}
public class Implem2 extends GenericClass<Implem2> {
#Override
public Implem2 returnMyself() {
return this;
}
}
public class Main {
public static void main(String[] args) {
Implem1 implem1 = new Implem1();
Implem1 again1 = implem1.returnMyself(); // Works fine
Implem1 again2 = implem1.returnMyself(); // Works fine
Implem2 again3 = implem1.returnMyself(); // Does not compile
}
}
Since you want to write these methods inside of subclasses, this appears to be possible. You can override a method and have a different return type as long as the new return type is an extension of the old one:
Can overridden methods differ in return type?

How to create an object of an abstract class and interface

How do I create an object of an abstract class and interface? I know we can't instantiate an object of an abstract class directly.
You can not instantiate an abstract class or an interface - you can instantiate one of their subclasses/implementers.
Examples of such a thing are typical in the use of Java Collections.
List<String> stringList = new ArrayList<String>();
You are using the interface type List<T> as the type, but the instance itself is an ArrayList<T>.
To create object of an abstract class just use new just like creating objects of other non abstract classes with just one small difference, as follows:
package com.my.test;
public abstract class MyAbstractClass {
private String name;
public MyAbstractClass(String name)
{
this.name = name;
}
public String getName(){
return this.name;
}
}
package com.my.test;
public class MyTestClass {
public static void main(String [] args)
{
MyAbstractClass ABC = new MyAbstractClass("name") {
};
System.out.println(ABC.getName());
}
}
In the same way You can create an object of interface type, just as follows:
package com.my.test;
public interface MyInterface {
void doSome();
public abstract void go();
}
package com.my.test;
public class MyTestClass {
public static void main(String [] args)
{
MyInterface myInterface = new MyInterface() {
#Override
public void go() {
System.out.println("Go ...");
}
#Override
public void doSome() {
System.out.println("Do ...");
}
};
myInterface.doSome();
myInterface.go();
}
}
There are two ways you can achieve this.
1) Either you extend / implement the Abstract class / interface in a new class, create the object of this new class and then use this object as per your need.
2) The Compiler allows you to create anonymous objects of the interfaces in your code.
For eg. ( new Runnable() { ... } );
Hope this helps.
Regards,
Mahendra Liya.
You can provide an implementation as an anonymous class:
new SomeInterface() {
public void foo(){
// an implementation of an interface method
}
};
Likewise, an anonymous class can extend a parent class instead of implementing an interface (but it can't do both).
public abstract class Foo { public abstract void foo(); }
public interface Bar { public void bar(); }
public class Winner extends Foo implements Bar {
#Override public void foo() { }
#Override public void bar() { }
}
new Winner(); // OK
"instantiate" means "create an object of".
So you can't create one directly.
The purpose of interfaces and abstract classes is to describe the behaviour of some concrete class that implements the interface or extends the abstract class.
A class that implements an interface can be used by other code that only knows about the interface, which helps you to separate responsibilities, and be clear about what you want from the object. (The calling code will only know that the object can do anything specified in the interface; it will not know about any other methods it has.)
If you are using someone else's code that expects a Fooable (where that is the name of some interface), you are not really being asked for an object of some Fooable class (because there isn't really such a class). You are only being asked for an instance of some class that implements Fooable, i.e. which declares that it can do all the things in that interface. In short, something that "can be Foo'd".
You write a class that derives from the abstract class or implements the interface, and then instantiate that.
What you know is correct. You cannot create an object of abstract class or interface since they are incomplete class (interface is not even considered as a class.)
What you can do is to implement a subclass of abstract class which, of course, must not be abstract. For interface, you must create a class which implement the interface and implement bodies of interface methods.
Here are orginal tutorial on oracle site, http://download.oracle.com/javase/tutorial/java/IandI/abstract.html and http://download.oracle.com/javase/tutorial/java/concepts/interface.html
You can not instantiate the abstract class or an interface, but you can instantiate one of their subclasses/implementers.
You can't instantiate an abstract class or an interface, you can only instantiate one of their derived classes.
In your example
MyAbstractClass ABC = new MyAbstractClass("name") {
};
You are instantiating any class that implements Suprising.
public abstract class AbstractClass { ... }
public interface InterfaceClass { ... }
// This is the concrete class that extends the abstract class above and
// implements the interface above. You will have to make sure that you implement
// any abstract methods from the AbstractClass and implement all method definitions
// from the InterfaceClass
public class Foo extends AbstractClass implements InterfaceClass { ... }
NO, we can't create object out of an interface or Abstract class because
Main intention of creating an object is to utilize the wrapped methods and data.
As interface don't have any concrete implementation hence we cannot.
For abstract class we may have concrete method or abstract method or both.
There is no way for the API developer to restrict the use of the method thats don't have implementation.
Hope help.
No, you are not creating the instance of your abstract class here. Rather you are creating an instance of an anonymous subclass of your abstract class. And then you are invoking the method on your abstract class reference pointing to subclass object.

Extending functionality of all implementations of an Interface?

I'm looking to create a set of functions which all implementations of a certain Interface can be extended to use. My question is whether there's a way to do this without using a proxy or manually extending each implementation of the interface?
My initial idea was to see if it was possible to use generics; using a parameterized type as the super type of my implementation...
public class NewFunctionality<T extends OldFunctionality> extends T {
//...
}
...but this is illegal. I don't exactly know why this is illegal, but it does sort of feel right that it is (probably because T could itself be an interface rather than an implementation).
Are there any other ways to achieve what I'm trying to do?
EDIT One example of something I might want to do is to extend java.util.List... Using my dodgy, illegal syntax:
public class FilterByType<T extends List> extends T {
public void retainAll(Class<?> c) {
//..
}
public void removeAll(Class<?> c) {
//..
}
}
You can achieve something like this using a programming pattern known as a 'decorator' (although if the interface is large then unfortunately this is a bit verbose to implement in Java because you need to write single-line implementations of every method in the interface):
public class FilterByType<T> implements List<T> {
private List<T> _list;
public FilterByType(List<T> list) {
this._list = list;
}
public void retainAll(Class<?> c) {
//..
}
public void removeAll(Class<?> c) {
//..
}
// Implement List<T> interface:
public boolean add(T element) {
return _list.add(element);
}
public void add(int index, T element) {
_list.add(index, element);
}
// etc...
}
Alternatively, if the methods don't need to access protected members, then static helper methods are a less clucky alternative:
public class FilterUtils {
public static void retainAll(List<T> list, Class<?> c) {
//..
}
public static void removeAll(List<T> list, Class<?> c) {
//..
}
}
What prevents you from just adding new methods to the interface?
If you can't just add the new functionality to old interface, you could consider making another interface and then an implementation which merely implements those two. Just to be clear, in code this is what I mean:
// Old functionality:
public interface Traveling {
void walk();
}
// Old implementation:
public class Person implements Traveling {
void walk() { System.out.println("I'm walking!"); }
}
// New functionality:
public interface FastTraveling {
void run();
void fly();
}
// New implementation, option #1:
public class SuperHero extends Person implements FastTraveling {
void run() { System.out.println("Zoooom!"); }
void fly() { System.out.println("To the skies!"); }
}
// New implementation, option #2:
public class SuperHero implements Traveling, FastTraveling {
void walk() { System.out.println("I'm walking!"); }
void run() { System.out.println("Zoooom!"); }
void fly() { System.out.println("To the skies!"); }
}
I think it's illegal because you can not guarantee what class T will be. Also there are technical obstacles (parent's class name must be written in bytecode, but Generics information get lost in bytecode).
You can use Decorator pattern like this:
class ListDecorator implements List {
private List decoratingList;
public ListDecorator(List decoratingList){
this.decoratingList = decoratingList;
}
public add(){
decoratingList.add();
}
...
}
class FilterByArrayList extends ListDecorator {
public FilterByAbstractList () {
super(new ArrayList());
}
}
There is a delegation/mixin framework that allows a form of this. You can define a new interface, implement a default implementation of that interface, then request classes which implement that interface but subclass from elsewhere in your hierarchy.
It's called mixins for Java, and there's a webcast right there that demonstrates it.
I'm afraid it's not clear what do you want to get.
Basically, I don't see any benefit in using 'public class NewFunctionality<T extends OldFunctionality> extends T' in comparison with 'public class NewFunctionality extends OldFunctionality' ('public class FilterByType<T extends List> extends T' vs 'public class FilterByType<T> implements List<T>')

Categories

Resources