Java Chain Inheritance with Lombok and Guice Injections - java

EDIT: This question really should be around Lombok and Guice instead of vanilla java inheritance.
I'm trying to implement a Java inheritance chain with Lombok and Guice injections, it works something like this:
Class 1
public abstract class Animal {
#NonNull protected String attr1;
protected abstract void method1();
void method0() {
// Some code that uses attr1
}
}
Class 2
public abstract class Mammal extends Animal {
#NonNull protected String attr2;
protected abstract void method2();
#Override
void method1() {
// some logic that uses attr2
method2();
}
}
Class 3
public class Wolf extends Mammal {
#Inject #NonNull private String attr1;
#Inject #NonNull private String attr2;
#Inject #NonNull private String attr3;
#Override
void method2() {
// some logic
}
}
Out there in the main program I have code that calls wolf.method1(). The problem here is that only wolf has all the attributes needed (due to Guice injections), whereas all the fields in Animal are undefined. I suspect I can probably do it in Vanilla Java, but things are going to get super messy (I have 6 attributes in Animal class and 5 more in Mammal). Is there a way to mix-and-match lombok's annotations (#NoArgsConstructor, #AllArgsConstructor, etc) to make this work?
Thanks.

Your abstract classes cannot be directly instantiated even if you add public constructors, because they are declared abstract. If you prefer, you can make the constructors protected to indicate they are only available to subclasses.
right that abstract classes can't really be instantiated, but why didn't the Java compiler catch this and stop complaining about not having a constructor?
Any class you write without an explicit constructor has an implicit no-args constructor. Any implicit no-args constructor implicitly calls its superclass's no-args constructor, even if that superclass is abstract. So if some class up the chain doesn't have a no-args constructor (because you explicitly gave it another constructor), then you code won't compile.
In the code you gave in your question, there are no explicit constructors, so every class does have an implicit no-args constructor. In your actual code, presumably you have written a constructor somewhere, which is why the implicit no-args constructor has not been added.

I propose:
use only interfaces for the entire hierarchy.
decouple behaviors and encapsulate them in separate classes.
use composition instead of inheritance, i.e. private SomeBehavior someBehavior; for every specific animal that needs it.
It will make your design better and solve the problem as well.
i.e.
public interface Mammals {
}
public interface Animal extends Mammals {
}
public interface Dog extends Animal {
}
and
public class TakeADump {
public void dump() {
}
}
public class TakeAPee {
public void pee() {
}
}
and then
public class Sheperd implements Dog {
private TakeADump dumpService;
private TakeApee peeService;
}
And now your dog can s... and p... :)
Also add
public class F... {
public void f...(<Animal> animal) {
// ... check it's an instance of the same or compatible animal or throw UnsupportedOperationException() if it's incompatible
}
}
:D
Of course it will make sense to create an abstract Animal.
i.e.
public class AbstractAnimal {
private TakeADump dumpService;
private TakeApee peeService;
private F... f...Service;
}
then
public abstract class AbstractDog extends AbstractAnimal implements Dog {
}
and
public class Sheperd extends AbstractDog {
public void lookAfterSheep() {
Sheep sheep = SheepLocator.findNearest();
// pee on a sheep
peeService.pee(sheep);
// dump on a sheep
dumpService.dump(sheep);
// f... a sheep
f...Service.mount(sheep);
}
}
So your mistake is using too much abstract when you can use interfaces.

When you are implementing concept of inheritance with some argument constructor it is good practice to have one default (no argument) constructor defined there. Because while creating object of child class compiler internally will call constructor of parent class.
e.g
class ABC {
}
class XYZ implements ABC{
}
public class Test{
XYZ obj= new XYZ() // this will internally call default constructor of XYZ and
//in that first statement will super()--> this will call default constructor of class ABC
}
if anyhow you have implemented argument constructor in parent class then compiler will not implement default constructor implicitly we need to define it explicit to make call to super constructor from child constructor. Or do a explicit call to argument constructor from child constructor.

Related

Interface extending a class

Let's say that I have an interface, and all classes that implement that interface also extend a certain super class.
public class SuperClass {
public void someMethod() {...}
}
public interface MyInterface {
void someOtherMethod();
}
//many (but not all) sub classes do this
public class SubClass extends SuperClass implements MyInterface {
#Override
public void someOtherMethod() {...}
}
Then if I'm dealing with an object of type MyInterface and I don't know the specific sub class, I have to hold two references to the same object:
MyInterface someObject = ...;
SuperClass someObjectCopy = (SuperClass) someObject; //will never throw ClassCastException
someObjectCopy.someMethod();
someObject.someOtherMethod();
I tried making the interface extend the super class, but it's a compiler error:
public interface MyInterface extends SuperClass {} //compiler error
I also thought of combining the interface and the super class into an abstract class like so:
public abstract class NewSuperClass {
public void someMethod();
public abstract void someOtherMethod();
}
But then i can't have a sub class that doesn't want to implement someOtherMethod().
So is there a way to signify that every class that implements an interface also extends a certain class, or do I have no choice but to carry around two references to the same object?
I think that the only solution you have would be to have a reference to both, but this indicates that you have a design flaw somewhere. The reason I say is because you should think of an interface as something that your implementing classes will always need. For example, a Car and Airplane both need a Drive() interface. A design reconsideration is probably worth your time. However, if you still want to follow that path, you can do the following:
public class ClassA {
public void methodA(){};
}
public abstract class ClassB extends Class A{
public void methodB();
}
After you have the above setup, you can now reference an object that has the two methods by doing the following:
ClassB classB = new ClassB();
classB.methodA();
classB.methodB();
Now you don't actually have to actually use two pointers to the same object.

Call constructor in an abstract class

Is it possible to call a constructor in a abstract class?
I read that this constructor can be called through one of its non-abstract subclasses. But I don't understand that statement. Can anybody explain this with an example?
You can define a constructor in an abstract class, but you can't construct that object. However, concrete sub-classes can (and must) call one of the constructors defined in the abstract parent class.
Consider the following code example:
public abstract class Test {
// abstract class constructor
public Test() {
System.out.println("foo");
}
// concrete sub class
public static class SubTest extends Test {
// no constructor defined, but implicitly calls no-arg constructor
// from parent class
}
public static void main(String[] args) throws Exception {
Test foo = new Test(); // Not allowed (compiler error)
SubTest bar = new SubTest(); // allowed, prints "foo"
}
}
You can't call an abstract class constructor with a class instance creation expression, i.e.
// Invalid
AbstractClass x = new AbstractClass(...);
However, in constructing an object you always go through the constructors of the whole inheritance hierarchy. So a constructor from a subclass can call the constructor of its abstract superclass using super(...). For example:
public class Abstract {
protected Abstract(int x) {
}
}
public class Concrete {
public Concrete(int x, int y) {
super(x); // Call the superclass constructor
}
}
As constructors of abstract classes can only be called within subclass constructors (and by chaining one to another within the same class), I typically make them protected... making them public would serve no purpose.
The normal rules apply if you don't specify a super(...) or this(...) call in a concrete subclass constructor - it's equivalent to a super(); statement at the start of a constructor, calling a parameterless constructor in the superclass... so there'd have to be such a constructor.
In this example Java program, we have an abstract class Servidor, which has one parametric constructor, which accepts name. Subclass provides that name to superclass while creating concrete instance of Servidor and overriding abstract method start(). Since this program compile and run fine you can definitely say abstract class can have constructors in Java.
public class AbstractConstructorTest {
public static void main(String args[]) {
Servidor Servidor = new Tomcat("Apache Tomcat");
Servidor.start();
}
}
abstract class Servidor{
protected final String name;
public Servidor(String name){
this.name = name;
}
public abstract boolean start();
}
class Tomcat extends Servidor{
public Tomcat(String name){
super(name);
}
#Override
public boolean start() {
System.out.println( this.name + " started successfully");
return true;
}
}
Output:
Apache Tomcat started successfully
You can obviously do something like:
public class ConcreteClass extends AbstractClass {
public ConcreteClass(){ // concrete class constructor
super(); // abstract class constructor
}
}
A constructor of an abstract class can be used only inside constructors of concrete classes inheriting from it.
Abstract and Concrete classes are something like Generalization and Specialization in Java and can be executed using inheritance. Let me explain with a plain and simple example. Say we have a class "DBConnector". It seems to be more generalized class and its meaning less to instantiate the class (which DB you are connecting to, driver vary for each DB right). Hence we can make DBConnector as abstract. That is the reason why we cannot basically instantiate Abstract classes.
Now we can create different concrete classes for each database extending the behavior of our concrete class like "OracelDBConnector", "MySQLDBConnector" etc., As we inherit the properties of abstract class into concrete class, we initialize the abstract class properties ideally using abstract class constructor using concrete class constructor using super(parameter list).
Thanks,
JK

What do you do when a subclass can't implement an interface method because the superclass has a final method with the same signature?

Let's say you have a class that extends Activity and implements MyInterface, where Activity contains public final void setProgress(int progress) and MyInterface contains public abstract void setProgress(int progress)
I need to override the method from the interface, but I can't because Activty says it's final and can't be overridden.
What do I do?
Example:
public class MyActivity extends Activity implements MyInterface
{
#Override
protected void onCreate(Bundle bundle)
{
//stuff goes here
}
//Cannot override the final method from Activity
#Override
public void setProgress(int progress)
{
}
}
Let's also extend this question and say you don't have access to the source of MyInterface to change it, what does one do in such situations?
Use a decorator Design Pattern.
and here's a simplified example of the decorator pattern.
(adapted from the interwebs and polygenelubricants' answer on SO)
Note: before we begin remove the abstract keyword from the interface, that's wrong syntax
The class hierarchy is restructured as static inner classes so that the whole example is contained in one compilation unit (as seen on ideone.com):
Here's a diagrammatic overview of intended class hierarchy
public class AnimalDecorator {
static interface Animal {
public String makeNoise();
public void wagTail();
//other methods
}
static class Dog implements Animal {
public final String makeNoise() { return "woof"; }
public final void wagTail() { //do wag tail action }
}
static class DogDecorator implements Animal {
//delegate
private Animal animal;
public DogDecorator (Animal animal){this.animal = animal;}
public String makeNoise() { animal.makeNoise();}
public void wagTail() { animal.wagTail();}
}
static class LoudDog extends DogDecorator {
#Override public String makeNoise() {
return "WOOF WOOF WOOF!!!";
}
}
}
So here we have a simple Animal hierarchy, with Dog subclass. We also have a DogDecorator decorator -- also an Animal -- that simply delegates all methods to another Animal. That is, it doesn't really do any effective decoration, but it's ready to be subclassed so that actual decorations can be added.
We only have two methods here, makeNoise() and wagTail(). We then create the class we want LoudDog and use it. (Consider the case where Animal has many methods; then Normal would be most valuable).
Note that we can even stack one decoration on top of another. The exact implementation details may vary, but this simplified example pretty much captures the essence of the decorator pattern.
Steps
Subclass the original "Component" class into a "Decorator" class (see UML diagram);
In the Decorator class, add a Component pointer as a field;
Pass a Component to the Decorator constructor to initialize the Component pointer;
In the Decorator class, redirect all "Component" methods to the "Component" pointer; and
In the ConcreteDecorator class, override any Component method(s) whose behavior needs to be modified.
See also
Effective Java 2nd Edition, Item 18: Prefer interfaces to abstract classes
Related questions
Interface vs Abstract Class (general OO)
Is it just me or are interfaces overused?
You cannot override the final method because in the Java programming language, the final keyword is used to define an entity which cannot later be changed.
form Java Language Specification
Never tried but can give it a try.
You must implement the MyInterface in subclass too and can override the setProgress method of MyInterface and not of its superclass.
Should say..a good question:)
Edit:
In this case, the class cannot override the final method. So either your interface will have the exact same signature as the parent class (hence the interface is implemented automatically by inheritance), or you create a method with a different name.
The solution would largely depend on the circumstances, there's no textbook solution here.
Don't have your MyActivity implement MyInterface and instead create anonymous or inner class that implements it.
This ways you still have access to all MyActivity components and functions from setProgress(int) which is completly separate from final Activity.setProgress(int).

abstract class with abstract fields and subclassing without casting

I created an abstract base class. It contains an object which should be extended by any subclasses:
public abstract class AbstractParent {
protected AbstractObject subMePlz;
// ... some fields that all subclasses need
public AbstractParent() {
this.subMePlz = createThisInYourExtendedClass();
}
public abstract AbstractObject createThisInYourExtendedClass();
}
the abstractObject:
public abstract class AbstractObject {
// ... some fields/methods that all subclasses need
}
What I want is to be able to use the extended field in the extended class without casting:
public class ExtendParent extends AbstractParent {
// .. some unique fields
public ExtendParent(){
super();
}
public ConcreteObject createThisInYourExtendedClass(){
return new ConcreteObject();
}
// what I want to do - no cast
public void doSomethingWithSubMePlzWithoutCastingIt() {
System.out.println(this.subMePlz);
}
// what I end up doing - gotta cast
public void doSomethingWithSubMePlzWithoutCastingIt() {
System.out.println((ConcreteObject)this.subMePlz);
}
}
Would needing a comparator change how I should implement this? - I'm thinking a generic comparator for a list of the AbstractObjects that could be used by its subclasses.
It sounds like you need to make it generic:
public abstract class AbstractParent<T extends AbstractObject> {
protected T subMePlz;
// ... some fields that all subclasses need
public AbstractParent() {
this.subMePlz = createThisInYourExtendedClass();
}
public abstract T createThisInYourExtendedClass();
}
public class ExtendParent extends AbstractParent<ConcreteObject> {
...
}
Note that calling non-private methods within a constructor is usually a bad idea - the subclass won't have been fully initialized yet, which can make it difficult to reason about how much you can really rely on.
You have two options:
Abandon the project to declare the field in the superclass. Instead, add an internal abstract "getter" method to your superclass -- basically, AbstractParent should have a method abstract AbstractObject getSubMePlz().
Use generics to set the type of subMePlz in your subclass: define AbstractParent<T> to have a T for its subMePlz field.
Personally, I frequently find option 1 to be very pleasantly extensible -- for example, you can have another subclass that narrows the getSubMePlz() return type without yet declaring it, which can be advantageous.
Why not use this -
super.subMePlz
instead of this -
(ConcreteObject)this.subMePlz
That way, you won't need a cast.
You just could save a copy of the object in the subclass but with the correct class.
public class ExtendParent extends AbstractParent {
ConcreteObject concreteObject;
public AbstractObject createThisInYourExtendedClass(){
ConcreteObject concreteObject = new ConcreteObject();
return concreteObject;
}
public void doSomethingWithSubMePlzWithoutCastingIt() {
System.out.println(concreteObject);
}
...

how to make constructor definition mandatory

I have an interface I that is implemented by a base class B. The base class is extended by a bunch of classes (A,C,D) that must init some of the protected vars declared in base class B. I'd like to make the declaration of a constructor mandatory in the subclasses (A,C,D), to discourage the user from relying on default constructor that's declared in B. Yet I do want the B's default constructor to execute automatically, since B can be used by itself as well. How can I accomplish this?
thanks
Use an abstract superclass of B with a private constructor:
public abstract class BSuper {
private BSuper() {
// initialize stuff
}
protected BSuper(some params) {
this():
// other init with parms
}
}
public class B extends BSuper {
public B(some other params) {
super(some params);
}
}
public class A extends B {
public A() {
super(some other params);
}
}
or similar
Make B's default constructor private and call this(); from within the parameterized constructor...
public class B {
private B() {
super();
}
public B( Foo foo ) {
this();
}
public static B createInstance() {
return new B();
}
}
Edit: Miss read the issue, removed abstract keyword from class declaration. Also added public static factory method for creating B class. It calls B's default constructor.
Just write a comment in the Javadoc that says "Use of default constructor is discouraged when subclassing." In my experience, trying to enforce that programmatically is not worth the effort and could cause problems latter on. Simple English will do.
If class B is going to have its own default constructor, what you want is impossible. When you derive from a class, you're telling the compiler that it should allocate memory for a base class object in every instance of the derived class. There's no way to tell a java compiler to suddenly take away some of the base class's functionality every time that something is inherited from it.
Also note that constructors and static factory methods can't be abstract, so even if B could be an abstract class you would have to do something like:
public class B {
B() {
initialize();
}
protected abstract void initialize();
}
...along with making sure that the derived classes implement default constructors that call super()

Categories