Construction of parent abstract class - java

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();

Related

Creating an intance of a Class via method of an Interface implemented by that class

I want to call the constructor of a class inside the method of an interface.
For example, if I have two classes B and C and they both implement SomeInterface, so that each of them has method foo().
interface SomeInterface {
public SomeInterface foo();
}
class B implements SomeInterface {
public B(int fst, int snd) {}
#Override
public SomeInterface foo() {
return new B(1, 1);
}
}
class C implements SomeInterface {
public C(int fst, int snd) {}
#Override
public SomeInterface foo() {
return new C(1, 1);
}
}
And let's say, for the sake of this question, that I have a lot more classes that implement SomeInterface and they all do the same thing, that is return new <nameoftheclass>(1,1)
and all these classes extend the parent class A.
Is there a way for me to create only one method in A such that if any of these classes use the foo method that is found in A it will call their constructor and just like that save me lines of code?
You can do something like this with reflection, although it will be prone to failure.
public SomeInterface foo() {
Constructor<? extends SomeInterface> c = getClass().getConstructor(int.class, int.class);
return c.newInstance( 1, 1);
}
You'll have to manage some exceptions, but is this what you're after?
The question would then be, where can this be used? Interfaces don't have a common constructor.
public interface SomeInterface{
default SomeInterface another(){
Constructor<? extends SomeInterface> c = getClass().getConstructor(int.class, int.class);
return c.newInstance( 1, 1);
}
}
That would work provided whatever the implementations try to use it have that constructor. There is no guarantee that constructor exists though. Maybe you would want it on an abstract class?
use the foo method that is found in A it will call their constructor and just like that save me lines of code?
You are getting it wrong. Class design decisions must be based on use cases and relationships of the classes in your domain. If your main criteria will be to spare some lines of code, you can end up with a coffee machine extending combine harvester because both of them have tree dimensions. Don't take a pill if you have no headache.
Parent class A that you've mentioned doesn't make any sense because method foo() returns an instance of SomeInterface interface which A doesn't implement (because if it does, its subclasses don't need to declare to implement it). I.e. A and SomeInterface are not compatible and compiler will not allow to type cast between them. Therefore, I'll omit the parent class.
As an example, the "template" you've provided might be useful, will be a situation when classes with similar functionality need to grouped together.
The interface can serve as a single entry point for the user of the code. Every class will implement the behavior defined by the interface, and only through the interface it'll be possible to get an instance of the class with a particular flavor of functionality. The actual classes will be hidden from the user.
Similarly, abstract class NumberFormat from the JDK provides a way to obtain different kinds of formatters, but actual implementations are hidden are not exposed (the approach shown below is far more simple than the actual way of how factory methods of the NumberFormat are implemented).
Note, interface and its implementations must reside in the same package.
public interface BaseInterface {
public static BaseInterface getInstance(Classifier classifier) { // factory
return switch(classifier) {
case A -> new A();
case B -> new B();
};
}
void doSomeThingUseful(); // behaviour that every class should implement
}
enum Classifier { A, B }
class A implements BaseInterface {
A() {}
#Override
public void doSomeThingUseful() {
System.out.println("Class A");
}
}
class B implements BaseInterface {
B() {}
#Override
public void doSomeThingUseful() {
System.out.println("Class B");
}
}
main() - demo
public static void main(String[] args) {
List<BaseInterface> items = List.of(BaseInterface.getInstance(Classifier.A),
BaseInterface.getInstance(Classifier.B));
for (BaseInterface item: items) {
item.doSomeThingUseful();
}
}
Output
Class A
Class B

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));

Can you automatically cast an object of one class to a subclass and call an overloaded method in Java?

I have the following setup:
class Base {};
class ImplA extends Base {};
class ImplB extends Base {};
class ImplC extends Base {};
Base baseFactory(int type) {
switch(type) {
case 0:
return new ImplA();
case 1:
return new ImplB();
case 2:
return new ImplC();
}
Base a = baseFactory(0);
Base b = baseFactory(1);
Base c = baseFactory(2);
List<Base> list = new ArrayList<Base>();
list.add(a);
list.add(b);
list.add(c);
// Somewhere else I have:
interface BaseHandler {
process(ImplA a);
process(ImplB b);
process(ImplC c);
};
Now, what I would like to be able to do is something along the lines of:
class Processor {
BaseHandler bh;
Processor(BaseHandler bh) {
this.bh = b;
}
void processList(List<Base> list) {
for (Base x : list) {
bh.process(x);
}
}
And then have a user implement BaseHandler and be able to construct a Processor to operate on each element in the Base list.
But, this does not work as process(Base) is not defined. It may seem simple to just add 3 if statements, but I already have a switch like structure in building instances of classes extending the Base. It seems unnecessary to repeat this over and over. Is there a way to achieve this idea without writing an intermediate step that determines the runtime class of each Base in the list and calls the appropriate method (in effect another switch case -- but it would be if's)?
I think one work around idea would be to make each Base have an abstract process method which needs to be implemented by the Impl classes. However, this is not acceptable in my situation since the user will not be implementing the Impl classes. Basically, I need process to be a user-defined callback. Further, it does not make sense for process to be a member of the Impl or Base classes since it is in no way related. It's a separate callback that needs to respond dynamically to the type it is called with. And the type is always guaranteed to be a subclass of Base.
You do need the "intermediate step" that you describe, but it need not be if statements. What you're looking for is double dispatch using the visitor pattern. Basically your Base class would have a method:
void accept(BaseHandler handler);
and each subclass would implement it as:
handler.process(this);
where this would resolve to the correct type in each subclass at compile-time.
What you're looking for is the Visitor pattern. You put an abstract method on Base, but all it does is call the appropriate method in BaseHandler:
public interface Base {
void acceptHandler(BaseHandler handler);
}
Then your concrete implementations override acceptHandler and call the correct overload.
public class ImplA implements Base {
public void acceptHandler(BaseHandler handler) {
handler.process(this);
}
}
At this point there's not much value in the overloading, and you'd be better off just giving your methods descriptive names.
It sounds like what you want is the Visitor pattern here:
public interface BaseVisitor {
void caseA(ImplA a);
void caseB(ImplB b);
void caseC(ImplC c);
}
public class MyVisitor implements BaseVisitor {
void visit(List<Base> bases) {
for (Base b : bases) {
b.accept(this);
}
}
public void caseA(ImplA a) { // ... }
public void caseB(ImplB b) { // ... }
public void caseC(ImplC c) { // ... }
}
public abstract class Base {
abstract void accept(BaseVisitor visitor);
}
public class ImplA {
public void accept(BaseVisitor visitor) {
visitor.caseA(this);
}
}
public class ImplB {
public void accept(BaseVisitor visitor) {
visitor.caseB(this);
}
}
public class ImplC {
public void accept(BaseVisitor visitor) {
visitor.caseC(this);
}
}

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