Java: Dealing with multiple complex interfaces without duplicate code - java

I am working with a Java API which requires me to implement a number of fairly large interfaces. However generally there is only one or two details that actually vary between implementations, so I made some abstract base classes to provide most of the implementation.
However now Ive come across cases where I need to extend from some other class and/or implement multiple such interfaces, and so I am unable to extend my abstract base classes.
In C++ I was able to use multiple inheritance, and also use some other tricks like below. However Java doesn't allow multiple inheritance, or generics to be used in this way.
class MyClass : public HelperForInterfaceA, public HelperForInterfaceB {...};
class template<class BASE> MyHelper : public BASE {...};
The best idea I have right now is to have the concrete implementation of my abstract helper class as a field, and then make all the interface methods forward to that field instance, with the field having a reference to the main object to implement the last details if needed.
class MyClass extends A implements IB, IC {
private static class B extends BAbstractHelper {
private A a;
public B(A a, int size) {
super(size);
this.a = a;
}
#Override
public boolean foo(int x, int y) {
return a.foo(x, y);
}
}
private static class C extends CAbstractHelper {
...
}
private B b;
private C c;
private int range;
#Override
public boolean foo(int x, int y) {
return x*x + y*y <= range*range;
}
#Override
public float bar(float x, int y, String s) {
return b.bar(x,y,s);
}
...
}
However this seems a bit of a pain, with a lot of wrapper methods required. Is there a better way of dealing with this?

A Java best practice is to prefer composition over inheritance. Keeps things simpler but creates more boilerplate code. You have the right idea to create delegate methods. A good Java IDE can generate all the boilerplate delegate methods code for you. Other languages on the JVM like Scala (with traits) make this easier.

Related

How to cast to a polymorphic type with a member not in interface

I have an interface like
public interface IFoo {
String getX();
...
}
and have several classes like
public class Bar implements IFoo {
public String getX() {
...
}
public String getY() {
...
}
}
The important thing here is that all of the classes that implement IFoo, like Bar, have the String getY() method, but this method is not part of the IFoo interface.
Now, I have some XML that I need to deserialize to a Java object. The XML can be an object of any of the IFoo implementing classes, but after deserializing, I will need to use the String getY() method.
Are there any concise or elegant ways to achieve this?
I have created another interface like
public interface IFooExtension extends IFoo {
String getY();
}
and have tried creating an instance of it like
String xml = ...;
IFooExtension fooExtension = (IFooExtension) XMLBeanSerializer.deserialize(xml);
but get an error when casting the XML to the object that says something object Instance of Bar cannot be cast to an object of type IFooExtension
ANSWERS:
The answers from GhostCat and Edwin Dalorzo are both great.
GhostCat explains that this is not possible in Java out of the box because Java does not support duck typing
Edwin Dalorzo provides a workaround for this issue by applying the Adapter design pattern
This is simply not possible in Java.
In order for any class X to be casted to some interface Y, there absolutely must be X implements Y in the source code side of things (or: a parent class of X doing that).
Java does not support the idea of "call me Y because I have all methods of Y" (in the sense of some object "being an instance of Y, because it has all Y methods).
From my understanding of your question, you know that XMLBeanSerializer.deserialize(xml) is going to give you a specific kind of object, an object of type A, B or C. Those types you know in advance.
Now, you also know that A, B, and C have a method with signature int getX(), but none of these types have a common interface with that method.
You also know that A, B, and C do have a common interface type Foo that implements int getY(). So, all the objects you deserialize can be assigned to a reference of type Foo and gain access to int getY(), but there is not a type that you can use for all those objects to gain access to both methods int getX() and int getY().
That's my understanding of your problem and based on that I believe we can implement a solution with an adapter pattern.
So, to start you have a common interface:
interface Foo {
int getY();
}
And a few deserializable objects from classes that implement it, plus an additional method:
class A implements Foo {
#Override
public int getY() { return 1; }
public int getX() { return 0; }
}
class B implements Foo {
#Override
public int getY() { return 2; }
public int getX() { return 0; }
}
class C implements Foo {
#Override
public int getY() { return 3; }
public int getX() { return 0; }
}
So, how can I deserialize an object of any of these classes and gain access to both methods through a common interface?
Adapter Solution
Well, obviously we can't do it the way it is. As other answers have pointed out, Java does not have duck typing.
However, we can simply build a new type hierarchy in which the classes implement both methods.
We start with an interface FooExt that exposes both methods.
interface FooExt extends Foo {
int getX();
}
Then we define an adapter class hierarchy based on this new interface:
class AAdapter implements FooExt {
private final A adaptee;
AAdapter(A adaptee) {
this.adaptee = adaptee;
}
#Override
public int getY() { return adaptee.getY(); }
#Override
public int getX() { return adaptee.getX(); }
}
class BAdapter implements FooExt {
//TODO: implement adapter
}
class CAdapter implements FooExt {
//TODO: implement adapter
}
And now we can do something like this:
public FooExt deserialize(String xlm) {
Object obj = XMLBeanSerializer.deserialize(xml);
if (obj instanceof A a) {
return new AAdapter(a);
}
if (obj instanceof B b) {
return new BAdapter(b);
}
if (obj instanceof C c) {
return new BAdapter(c);
}
throw new AssertionError("Unknown object type: " + obj);
}
As you can see the adapter pattern uses delegation (which is a form of object composition) instead of inheritance to adapt the object to a new interface that support both methods.
This follows that principle of: "Favor composition over inheritance".
Finally, in the call site we can do somewhat as follows:
FooExt fe = deserialize(xml);
int x = fe.getX();
int y = fe.getY();
Proxy Solution
The following is a proxy-based version of the code that would save you the time of having to implement a full class hierarchy.
A proxy pattern can help you wrap the adapted in a reflection handler that can help you find the method you want to invoke.
So, consider the following code to create a proxy around the adapted. The proxy is of type FooExt.
static FooExt createProxyAdapter(Foo adaptee) {
ClassLoader cl = Foo.class.getClassLoader();
Object adapter = Proxy.newProxyInstance(cl, new Class<?>[]{FooExt.class},
(Object proxy, Method method, Object[] args) -> {
if(method.getName().endsWith("getX")) {
//then find the method in the adaptee
var m = adaptee.getClass().getMethod("getX");
return m.invoke(adaptee);
}
//otherwise call the method from FooExt.
return method.invoke(adaptee, args);
});
return (FooExt) adapter;
}
And now you can do somewhat as follows:
Foo a = new A();
FooExt fa = createProxyAdapter(a);
int y = fa.getY();
int x = fa.getX();
Works like a charm!
If there are too many classes to adapt, then this solution is, perhaps, preferable. If there are only a few classes, then I would prefer the first one, since I would consider the code easier to maintain, debug, follow, etc.
Whether you consider these two ideas an elegant solution or not is an entirely different discussion :-)

cast or create obj1 from obj2 where obj1 and obj2 extends same abstract class

For example I have:
public abstract class SomeAbstract {
private int a;
private int b;
..
private int z;
}
public class A extends SomeAbstract {
private String aField;
}
public class B extends SomeAbstract {
private long bField;
}
(default constructors/setters/getters are omitted)
I have some instance of a class A and i wanna create
instance of a class B from A(abstract fields).
Yes, I can use abstract class constructor or create constructor for class B like this :
public B(A a) {
this.a = a.getA();
this.b = a.getB();
..
this.z = a.getZ();
}
But since I have many fields this does not look nice and convenient
Is there another way?
You can create a constructor in the super class that receives another super class.
public abstract class SomeAbstract {
/* attributes... */
public SomeAbstract() {
}
protected SomeAbstract(SomeAbstract another) {
this.a = another.a;
/* and on... */
}
}
And reuse this constructor in sub classes:
public class B extends SomeAbstract {
public B(A a) {
super(a);
this.specificAttribute = a.somethingElse;
}
}
If you have that many fields and don't want/need to create the whole code manually, you can use an external library that helps you with the mapping between classes. Some options are:
Dozer that maps data between objects. The configuration can be done through XML or annotations. This library works (AFAIK) using reflection, so it may have a direct impact on the performance of your application.
Orika that generates byte code at runtime to map data between objects. The configuration is done at design time. This library works (AFAIK) using reflection, so it may have a direct impact on the performance of your application, when I tested it, the execution time was faster than Dozer (about 7x faster).
MapStruct that will generate code to map the classes (using getters and setters, validating nulls and on) and this code will be available for at runtime. The configuration is done at design time through annotations. This library works (AFAIK) using Java code, so it's similar to the normal execution of the code (e.g. execute b.setValue(a.getValue())).

Is inheritance possible without Encapsulation in java?

Is inheritance possible without Encapsulation in java?
Is this possible?
Yes, it is possible. Inheritance and Encapsulation do not depend on each other, but when used both, they provide more flexible and powerful application structures.
For instance, below, there is inheritance without encapsulation. Note - that it is a bad approach, and do not use this approach in your projects. It is just for the demonstration purposes.
class A {
public int a;
public int b;
public String c;
public A() {
}
protected void someMethod() {
}
}
class B extends A {
// a, b, c from the parent A class are accessible here
public int d;
public String e;
public B() {
super();
}
// someMethod() is accessible here
}
In the code above, there is no encapsulation implemented, all class fields are public, and can be changed from outside.
But this approach prevents you from changing the structure of your classes withour affecting the rest of your code.
And it is strongly recommended to combined use of inheritance and encapsulation in your applications.
Hide your class structure and implementations over this structure. And show (make public) only methods to operate with the class instance internals from the outside.

Private Access Specifier usage in Java Inheritance

We can access the Super Class methods which consists of operations on private data members and print the results.But why can't I print the private data members of Super Class with the SubClass object calling them in my main function? Someone please explain me.
Here is the example below.
class SuperClass1
{
private int a;
private int b;
SuperClass1(int p,int q)
{
a=p;
b=q;
}
SuperClass1(SuperClass1 obj)
{
a=obj.a;
b=obj.b;
}
SuperClass1()
{
a=-1;
b=-1;
}
int Vol()
{
return a*b;
}
}
class SubClass1 extends SuperClass1
{
int c;
SubClass1(int p,int q,int r)
{
super(p,q);
c=r;
}
SubClass1(SubClass1 obj)
{
super(obj);
c=obj.c;
}
SubClass1()
{
super();
c=-1;
}
}
public class Super
{
public static void main(String[] args)
{
SubClass1 obj1=new SubClass1();
//System.out.println("The values of obj1 are:"+obj1.a+""+obj1.b+""+obj1.c);
int vol=obj1.Vol();
System.out.println("The volume is :"+vol);
}
}
security and encapsulation
The superclass is letting its subclasses use only the public and protected methods/fields.
This allows the designer of the superclass to change the implementation of these methods if he sees it better, without breaking the subclass's correctness.
A text book example is a complex number class.
The programmer using this class only needs its functionality, he doesn't care if the implementation is with imaginary and real fields or with radius and theta fields [two distinct ways to represent complex number].
It allows the designer of the ComplexNumber class more freedom if he wants to change the class in later versions, and it also allows the user less worries: he doesn't need to take care for all the details, some are being taken care of for him.
Bonus: note you can break this behavior and access private fields and methods by using reflection - but when you do so - all bets are off, and you do it on your own responsibility.
Your question isn't very clear without an example, but I suspect that the "methods which consist of operations on private data members" aren't private. It doesn't matter that they work by accessing private data - they're not private themselves. It would be pretty pointless having access modifiers if public methods could only access other public members etc.
The whole point of encapsulation is that only the class itself should care about implementation details such as the fields in question, but can expose a contract in terms of its public (and protected) API. Code outside the class shouldn't care about the private implementation details.
JLS says:
Members of a class that are declared private are not inherited by
subclasses of that class. Only members of a class that are declared
protected or public are inherited by subclasses declared in a package
other than the one in which the class is declared.
So, to answer you question. No, private members are not accessible by subclasses.
Private members are not inherited; only the protected and public members are.
If possible, you can do one of the following:
Make the private properties of the superclass protected
Make public getters (and setters if needed) for the private properties

Extending Java Enums

I have a question regarding the best design pattern for code reuse when dealing with Java enums. Basically, what I'm trying to achieve is being able to define several enums that model static business collections (sets of constants), but I'd also like to share behavior between them, with minimal coding.
This is trivial to achieve with class inheritance from abstract classes but, since Java enums cannot be extended (they can only implement interfaces), this type of work is tedious and involves a lot of error prone copy/paste work (copying the code from enum to enum). Examples of "business logic" that should be shared among all enums includes converting from/to Strings, instance and logical comparison, etc.
My best shot right now is using helper classes in conjunction with business interfaces, but this only goes so far in reducing code complexity (as all enums still have to declare and invoke the helper classes). See example (just to clarify):
public enum MyEnum {
A, B, C;
// Just about any method fits the description - equals() is a mere example
public boolean equals(MyEnum that) {
ObjectUtils.equals(this, that);
}
}
How do StackOverflowers deal with this "language feature"?
You can move the reusable logic to dedicated (non-enum) classes and then have the enums delegate to those classes. Here's an example:
[Side note: the inheritance of PlusTwo extends PlusOne is not recommended (b/c PlusTwo is not PlusOne). It here just to illustrate the point of being able to extend an existing logic.]
public interface Logic {
public int calc(int n);
}
public static class PlusOne implements Logic {
public int calc(int n) { return n + 1; }
}
public static class PlusTwo extends PlusOne {
#Override
public int calc(int n) { return super.calc(n) + 1; }
}
public static enum X {
X1, X2;
public Logic logic;
public int doSomething() {
return logic.calc(10);
}
}
public static enum Y {
Y1, Y2;
public Logic logic;
public String doSomethingElse() {
return "Your result is '" + logic.calc(10) + "'";
}
}
public static void main(String[] args) {
// One time setup of your logic:
X.X1.logic = new PlusOne();
X.X2.logic = new PlusTwo();
Y.Y1.logic = new PlusOne();
Y.Y2.logic = new PlusTwo();
System.out.println(X.X1.doSomething());
System.out.println(X.X2.doSomething());
System.out.println(Y.Y1.doSomethingElse());
System.out.println(Y.Y2.doSomethingElse());
}
I would do the same, or combine the Enums into a super-enum.
With Java 8 this will be easier. You will be able to define a default implementation for interface methods and have the enum extend the interface.
I rarely find enums useful, except for representing finite states in which case they do not need behavior.
I would suggest refactoring enums that need behavior into classes with a Factory.
This might look a bit ugly, but generally can offer you the required functionality.
You can have interface
public interface MyEnumInterface<T extends Enum<T>> {
String getBusinessName();
T getEnum();
}
Implementation
public enum OneOfMyEnums implements MyEnumInterface<OneOfMyEnums>{
X, Y, Z;
#Override
public String getBusinessName() {
return "[OneOfMyEnums]" + name();
}
#Override
public OneOfMyEnums getEnum() {
return this;
}
}
And utility class instead of your parent class
public class MyEnumUtils {
public static <T extends Enum<T>> String doSomething(MyEnumInterface<T> e){
e.getBusinessName(); // can use MyEnumInterface methods
e.getEnum().name(); // can use Enum methods as well
return null;
}
}

Categories

Resources