reuse same class in different class hierarchies - java

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.

Related

Construction of parent abstract class

Java newbie here.
I got two classes (let´s call them A and B) and some of the methods (e.g. doSomething(...)) they contain are pretty much similar in the sense that they actually share same code. I decided to make my code more effective and use some sort of parent abstract class C from which the classes A, B will inherit.
Here is my issue. Method doSomething in class A has following signature:
doSomething(VievForA view, ...)
while same method doSomething in class B has signature like:
doSomething(VievForB view, ...)
As you can see the method doSomething uses different type of first parameter so I don´t know how to solve this in the abstract class.
What´s the correct way to construct the class C and what should the method doSomething look like?
I hopefully explained my situation well, otherwise I can add some more pseudocode.
You can also have a base view class which will get inherited by ViewA and ViewB and use ViewBase as the parameter for doSomething.
You can structure your code using Java generics as follow:
// View Classes
//====
/**
* The generic view parent class
*/
public abstract class GenericView{
}
/**
* The specific A view class
*/
public class ViewForA extends GenericView{
//...
}
/**
* The specific B view class
*/
public class ViewForB extends GenericView{
//...
}
// View Handler Classes
//====
/**
* The generic view handler
* #param <T> The view object that extends from GeneriView
*/
public abstract class C<T extends GenericView>{
private void doGenericSomething(GenericView t) {
//Do something generic on all views
}
//Do something specific on specific view
abstract void doSpecificSomething(T t);
//Do all stuff
protected void doSomething(T t){
doGenericSomething(t);
doSpecificSomething(t);
}
}
/**
* The specific A view handler
*/
public class A extends C<ViewForA>{
#Override
void doSpecificSomething(ViewForA view) {
//Do your stuff with viewForA
}
}
/**
* The specific B view handler
*/
public class B extends C<ViewForB>{
#Override
void doSpecificSomething(ViewForB view) {
//Do your stuff with viewForB
}
}
This way you can insert your common code on doGenericSomething(GenericView t) body at C class and then let each specific view class such as A and B classes to implement the specific code on doSpecificSomething(ViewForSpecific t) where ViewForSpecific is a class that inherits from GenericView ( like ViewForA and ViewForB in the shared code ).
You could use a common inherited class as parameter for the method:
doSomething(CommonViev view, ...)
{
if (view instanceof VievForA)
{
VievForA vievForA = (VievForA)view;
...
}
else if (view instanceof VievForB)
{
VievForB vievForB = (VievForB)view;
...
}
}
In case you are trying to maintain two classes A and B extending C,
then in C class, you make declaration like this.
doSomething(Object view, ...)
and In class A or class B, use like below
doSomething(Object view, ...){
VievForA(B) vievForA(B) = (VievForA(B)) view; //basically typecast it as per child class
}
Assuming your doSomething() has code that repeats itself you could implement common code in the abstract class C and use it in the implementation in A or B.
abstract class C {
protected Result doSomething(CommonStuff common){
// doing common stuff and
return result; // returning the result
}
}
class A extends C {
public void doSomething(ViewForA view, ..){
CommonStuff common = view.getStuff();
Result result = this.doSomething(common);
view.applyResult(result);
}
}
But this is very ... abstract example. If your ViewForA and ViewForB have a common interface of any kind it would even be better to use this. Once I used the common Interface like this:
abstract class C {
abstract protected ViewInterface getView();
protected void doSomething(){
this.getView().doStuffWithView();
}
}
class A extends C {
private ViewForA myViewForA;
#Override
protected ViewForA getView(){
return this.myViewForA;
}
}
Then the abstract class can handle the doSomething by assuming that there will be any kind of common View instance to be used. And the classes A and B will automatically implement the common doSomething and you can use it like
A a = new A();
a.doSomething();

When I extend an interface A with interface B, will A's methods be available for free to B's implementors?

I'm curious how this all works. I have an interface, let's call it A. When I look at A, it has most of the methods I need, but not all, and I don't have control over interface A, so I extend it with interface B which implements the 1 or whatever number of methods that I need on top of A.
public interface B extends A {
String doSomethingFun(String blah);
}
A has an implementation class called Client. In just a second I'm going to create my own implementation class of B called MyDefaultClient.
I then create a concrete class that implements B, like this:
#Component
public class MyDefaultClient implements B {
private A myClient;
#Autowired
public MyDefaultClient(A myClient) {
this.myClient = myClient;
}
#Override
public String doSomethingFun(String filename) {
// custom business logic
}
#Override
public String serviceName() {
return myClient.serviceName();
}
#Override
public void close() {
myClient.close();
}
}
serviceName() and close() are methods that A forces its implementors to implement. There are other methods though that have default implementations that aren't forcing me to implement them, I assume simply because they have default implementations.
At this point I have a concrete class that I can instantiate in other places and call all of both A and B's methods on it. But is that only because in the interface there are default implementations for these methods, like this?
default Blah someMethodInA(String thing) {
throw new UnsupportedOperationException();
}
If I use this code and call myDefaultClient.doSomethingFun("hello") I'm pretty certain that will do the thing I want it to do. But what about if I call myDefaultClient.someMethodInA()? Will it call the implemented method in Client, which is A's implementor? Or will it fall on the floor and complain with an UnsupportedOperationException? If the latter, is there any way I can structure this so that I can call all of A's methods from B's implementor?
If you want MyDefaultClient to inherit implementations from Client, then it has to extend Client, like this:
class MyDefaultClient extends Client implements B
{
...
}
Then, if Client implements A, you will only have to provide implementations for the new methods that B adds.
or... you can continue your current pattern and explicitly delegate all the calls you want to a field of type A, but you will have to do them all explicitly, even the methods with default implementations. The default implementations will continue the throw exceptions if you don't override them.
An interface can have any number of default methods. Check this for more details. Given below is an example to demonstrate how default methods and extending an interface work:
public interface InterfaceA {
public void toBeImplementedA();
default void hello() {
System.out.println("Hello");
}
default void hi() {
System.out.println("Hi");
}
}
public interface InterfaceB extends InterfaceA {
public void toBeImplementedB();
}
public class AnImplClass implements InterfaceB {
#Override
public void toBeImplementedA() {
System.out.println("toBeImplementedA");
}
#Override
public void toBeImplementedB() {
System.out.println("toBeImplementedB");
}
}
public class Main {
public static void main(String[] args) {
InterfaceB obj = new AnImplClass();
obj.toBeImplementedA();
obj.toBeImplementedB();
obj.hello();
obj.hi();
}
}
Output:
toBeImplementedA
toBeImplementedB
Hello
Hi
Feel free to comment in case of any doubt.
Interfaces can contain default methods. These were added to Java so that an interface could be updated without forcing implementing code to be rewritten.¹
Default methods provide an implementation if your implementing class does not implement them.
When you call methods on an object, the overridden method is always called.
Any other implementations in the super classes / interfaces are used when there is a lack of implementation.
Even if you refer to MyDefaultClient as A,
A myImplementation = new MyDefaultClient();
Under the hood myImplementation is still an instance of MyDefaultClient even though the code views it as A. Therefore your overriden method will be used when doSomethingFun is called.
#Override
public String doSomethingFun(String filename) {
// custom business logic
}
¹ Source: https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

Java polymorphism: finding the right design pattern

Disclaimer: I know there are a lot of questions about polymorphism out there, but I couldn't find a suitable answer for my problem. If your Google-fu is better than mine, please forgive the dupe.
I have a model using inheritance, such as in the example below.
public abstract class Base {
// ...
}
public class ConcreteA extends Base {
private String someString;
// ...
}
public class ConcreteB extends Base {
private boolean someBool;
// ...
}
And I also have a List<Base>, which is composed of objects that are either ConcreteAs or ConcreteBs.
I need to generate a graphical view for each object in the list, but the resulting element is not the same for ConcreteAs and ConcreteBs. From the example above, the view for ConcreteA would be a text field, while the view for a ConcreteB would be a check box.
How can I achieve this using OO principles?
The problem that you have is that you somewhere return a List<Base> when the caller must know the concrete type.
Usually this is caused because one tried to make a method more generic. E.g. if someone has this service methods
public List<ConcreteA> doSomethingA(){ ... }
public List<ConcreteB> doSomethingB(){ ... }
he might think it is a better idea to introduce a superclass, Base so that both methods can be substituted by
public List<Base> doSomething(){ ... }
This is a good idea if the caller is only interessted in a Base object. This means that ConcreateA and ConcreteB have some common behavior that the caller only depends on.
But in your case it seems that the caller needs the concrete type information that is not available anymore, because of the more generic method.
So you either must preserve or reconstruct the type information.
Preserve the type by using a custom return type instead of making the method generic
public class Result {
private List<ConcreteA> concreteA;
private List<ConcreteB> concreteA;
}
public Result doSomething();
Recunstruct the type information using instanceof
Reconstruct the type information by introcucing a visitor pattern.
Not a pattern - this is what abstraction is all about. Declare a method you want all subclasses of Base to implement and each must implement it in their own way.
Obviously you would pass parameters and/or get results of the methods.
public abstract class Base {
abstract void graphicalView();
}
public class ConcreteA extends Base {
#Override
void graphicalView() {
}
}
public class ConcreteB extends Base {
#Override
void graphicalView() {
}
}
public void test() throws IOException {
List<Base> bases = new ArrayList<>();
for ( Base b : bases ) {
b.graphicalView();
}
}
I think you're looking for Visitor Design Pattern.
From Wikipedia :
In object-oriented programming and software engineering, the visitor
design pattern is a way of separating an algorithm from an object
structure on which it operates. A practical result of this separation
is the ability to add new operations to extant object structures
without modifying the structures. It is one way to follow the
open/closed principle.
In essence, the visitor allows adding new virtual functions to a
family of classes, without modifying the classes. Instead, a visitor
class is created that implements all of the appropriate
specializations of the virtual function. The visitor takes the
instance reference as input, and implements the goal through double
dispatch.
In such cases, I usually use generics something like this
public abstract class Base <T extends Shape>{
public abstract T drawShape();
}
public class ConcreatA extends Base<Circle> {
#Override
public Circle drawShape() {
return null;
}
}
public class ConcreatB extends Base<Square> {
#Override
public Square drawShape() {
return null;
}
}
So now you can use list of Shapes

What is the best practice in Java to set a constant required in subclasses?

I have the following situation:
A parent class has a function that depends on a constant. But the only valid place to define that constant is in subclasses (parent class cannot define the constant's value, but it can be used with the constant undefined in 99% of use cases - the constant is a default to use if a specific configuration element is missing).
However, I would like to enforce that any child class inheriting from that parent class must define the value for the constant, since any child classes have to be able to use the other 1% of functionality.
What is the best practice to implement this enforcement in Java, ideally at compile time? (clearly, at runtime, I can simply check if the constant is null/empty in the method using it).
My own solution was to implement a value-getter for the constant as an abstract method in the parent class, and call that in combination with the real setter in the constructor; something like this:
public class HelperClass1 {
private String myConstant;
public void setMyConstant() {} // implemented obviousy
public void myMethod() { // Called from ParentClass's methods
// Do something useful with myConstant
}
}
import HelperClass1;
public abstract class ParentClass {
ParentClass() {
HelperClass1.setMyConstant( getMyConstantValue() );
}
public abstract void getMyConstantValue();
}
public class ChildClass1 extends ParentClass {
public void getMyConstantValue() { return "BUZZ"; }
}
public class ChildClass2 extends ParentClass {
} // Fails to compile without getMyConstantValue()
However, (a) This implementation has a problem (I can't use ParentClass itself, since it's now abstract) without subclassing; and (b) since I'm not a Java developer, I'm afraid that this isn't the best or the most elegant solution. So I'd like to know if there's a best practices approach that improves on what I implemented.
Provide two constructors for the parent class:
One is a protected constructor which takes the constant as an argument.
The other is private constructor which can construct instances of the parent class without setting the constant.
Provide a factory method for the parent class which can call the private no-constant constructor.
Classes that want to get an instance of the parent class can call the factory method. But child classes that want to inherit from the parent class have to call the protected constructer, which can validate that a valid constant was passed.
public class ParentClass {
private final SomeClass myConstant;
protected ParentClass(SomeClass aConstant) {
if (null == aConstant) {
throw new IllegalArgumentException("...");
}
myConstant = aConstant;
}
private ParentClass() {
myConstant = null;
}
public static ParentClass getInstance() {
return new ParentClass();
}
}
public class ChildClass {
public ChildClass() {
super(new SomeClass(42));
}
}
This isn't perfect. Someone could write a child class that passes a bad constant to the superclass constructor, and it wouldn't actually fail until some code tried to construct an instance of the child class.

Issues with method overriding and generics in 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());
}
}

Categories

Resources