A elegant way to implement ID on a abstract class - java

I have an abstract class. I want that every instance has a unique ID. I have implemented:
public abstract class MyAbstractClass{
static AtomicInteger nextId = new AtomicInteger();
private int id;
public MyAbstractClass() {
id = nextId.incrementAndGet();
}
}
public class MyClass extends MyAbstractClass {
public MyClass(){
super();
}
}
This approach works except the part there is nothing forcing the subclass to call the constructor.
Is there a way to implement a global ID for an abstract class?

there is nothing forcing the subclass to call the constructor.
There is nothing you can do to stop the subclass from calling super() unless parent constructors are built hierarchically wrong.
By "hierarchically wrong", I meant there is a parent constructor that isn't based on its no-argument constructor. For instance,
public MyAbstractClass() {
id = nextId.incrementAndGet();
}
public MyAbstractClass(String s) {
// ignores to call this();
}
Otherwise, any child will eventually call super(), and, thus, trigger your id initialisation.

Related

use abstract superclass' constructor by default?

Is something like this possible
abstract class AbstractSuperClass {
private Entity entity;
public AbstractSuperClass(Entity entity) {
this.entity = entity;
}
public abstract void operate();
}
public class SubClass extends AbstractSuperClass {
public void operate() {
this.entity.doVoidMethod(); // is this.entity defined in instances of SubClass ?
}
}
// ... somewhere else
Entity instantiatedEntity = new Entity();
SubClass instance = new SubClass(instantiatedEntity);
instance.operate(); // does this call this.entity.doVoidMethod() inside of instance?
I want to be able to skip writing my own constructors in subclasses of an abstract class I'm writing. All of the constructors would be identical in every subclass.
If I skip writing a constructor for a subclass of an abstract class (is this even allowed?) does the abstract class' constructor get used by default?
First of all, if you don't define constructors, a default one with no argument is considered.
In other words, if you want to use new SubClass(instantiatedEntity); you must define the constructor within the SubClass that takes a single argument of type Entity.
In other words, you cannot skip writing your own constructors in case you want to pass a parameter.
Secondly, within your SubClass, you cannot call this.entity.doVoidMethod();. This because the entity attribute is private within the base class and therefore not accessible by the SubClass.
Furthermore, within AbstractSuperClass you defined public abstract Operate();. You probably meant public abstract void operate();. There's a similar mistake in the SubClass.
I want to be able to skip writing my own constructors in subclasses of an abstract class I'm writing. All of the constructors would be identical in every subclass.
You can't. Constructors are not inherited in Java:
Java Constructor Inheritance
The only quasi-exception is the default constructor. However it is strictly speaking not inheritance. If there are no constructors, the default one is added and it will call super().
If I skip writing a constructor for a subclass of an abstract class (is this even allowed?) does the abstract class' constructor get used by default?
No. Constructors of superclass are neither inherited nor copied.
According to your code above, you are using subclass is extending from an abstract class.
abstract class A{
A(){
//todo: some work
}
abstract methodA();
methodB(){
//todo:something: implementation within the abstract class.
}
}
class B extends A{
B(){
super(this);
}
}
I believe to use abstract constructor you would use the super keyword.
Some thoughts (1) you should make entity "protected" instead of "private" - that's how you make it available in the subclass, (2) it helps to use accessor methods (getter/setter) which can be inherited by subclass unlike non-defaul constructors, (3) the operate method needs a return type (I used void below), (4) the operate method needs the same signature (type sensitive name and argument types) in order to override (5) it is good practice to annotate overridden methods with #Override.
public abstract class AbstractSuperClass {
protected Entity entity;
public AbstractSuperClass() {
}
public AbstractSuperClass(Entity entity) {
this.entity = entity;
}
public setEntity(Entity entity) {
this.entity = entity;
}
public abstract void operate();
}
public class SubClass extends AbstractSuperClass {
#Override
public void operate() {
this.entity.doVoidMethod(); // protected entity is available in subclass
}
}
// ... somewhere else
Entity instantiatedEntity = new Entity();
SubClass instance = new SubClass(); // default constructor
instance.setEntity(instantiatedEntity); // inherited method
instance.operate(); // yes calls entity.doVoidMethod()

Sub-class casting for methods

OK, so I'll start this with an example:
Let's say we have an abstract class with an interface variable, which is initialized in the constructor. The abstract class itself has a getter for that variable, it's subclasses have implementations of the interface in the constructor.
Now, the problem I'm getting is that when trying to call the getter of any of the subclasses (which is only declared in the superclass, but it should use the variable declared in their constructors) it doesn't return the implementation, it returns the interface itself.
public abstract class AbstractClass {
private final ExampleInterface exampleInterface;
public AbstractClass(ExampleInterface exampleInterface) {
this.exampleInterface = exampleInterface;
}
public ExampleInterface getExampleInterface() {
return this.exampleInterface;
}
}
public class AbstractClassSubclass extends AbstractClass {
//Instead of the interface itself, I provide my constructor it's implementation
public AbstractClassSubclass(ExampleInterfaceImplementation exampleInterfaceImpl) {
super(exampleInterfaceImpl);
}
}
public class TestClass {
private void testMethod() {
AbstractClassSubclass test = new AbstractClassSubclass(
new ExampleInterfaceImplementation()
);
//Would return ExampleInterface, instead of ExampleInterfaceImplementation
test.getExampleInterface();
}
}
Update
I believe I have fixed this using type parameters.
I'm sure I have tried it before but had a few problems...
Now it works perfectly.

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.

Java inheritance: Reducing visibility in a constructor vs inherited method

In the following code, the constructor of Child has reduced visibility from public to private, which is allowed. The inherited methods, such as test(), cannot have reduced visibility. Why does Java operate this way?
class Parent {
public Parent(){}
public void test()
{
System.out.print("parent test executed!");
}
}
class Child extends Parent{
private Child(){}
private void test(){
System.out.print("child test executed!");
}
}
Constructors are not inherited, so Child() doesn't override Parent().
As for the methods, if you have (if Child() were public)
Parent p = new Child();
p.test();
Had it been allowed, this would be invoking a private method. So narrowing the access while overriding is not permitted.
When extending a class you are stating that your class is an extension of the parent class ("IS-A" relationship). What this means is that your class will have all methods of your parent class. This is the same as implementing an interface in java except you gain the method definitions (and fields) from your parent and not just methods declared in the interface. In interfaces constructors are not present because they are not methods. Constructors are special as they belong entirely to the class they are declared on. They declare how to construct only themselves.
In order to construct an object you must know that objects class.
class A {
private message;
private A() {
message = "You created an A";
}
public A(String message) {
this.message = message;
}
public void printMessage() {
System.out.println(message);
}
public static A createAnA() {
return new A();
}
}
class B extends A {
public B() {
super("You created a B");
}
}
A anA = new B(); // This will work
A anotherA = new A(); // This is not allowed as the constructor is private
A yetAnotherA = A.createAnA(); // This works too
So when we constructed B we can say that it is an A. Even though the constructor A is private this is due the constructor not being a part of the interface. The only thing we are saying about B when we assign it to a field of type A is that it has the methods of declared in A. In this case printMessage and createAnA.
That is why you can make the constructor private without changing the definition of the class. Now, why are you not allowed to make the method private when overriding a parents signature. This comes to having varying definitions of the [class].method(). Let's say that you could make your method private. Let's say that you declared a printMssage in the B class. Your reasoning is that you want that method for your use only inside the method and you want your parents printMessage to be used when called externally. Now, you wrote a method like this in the B class.
public void adjustMessage(String additional) {
message = getMessage() + additional();
}
Which version of get message would be executed? Your private one or the public one of your parents? The Java dispatcher would of course choose the public one as it is the one declared in the interface. So we we look at this example we can see if you did make your method have different a lower privilege your method could never be dispatched too which would just make things confusing for the reader.
This is a very good question.

In Java, why can't I declare a final member (w/o initializing it) in the parent class and set its value in the subclass? How can I work around?

In a Java program, I have multiple subclasses inheriting from a parent (which is abstract). I wanted to express that every child should have a member that is set once only (which I was planning to do from the constructor). My plan was to code s.th. like this:
public abstract class Parent {
protected final String birthmark;
}
public class Child extends Parent {
public Child(String s) {
this.birthmark = s;
}
}
However, this seems to not please the Java gods. In the parent class, I get the message that birthmark "might not have been initialized", in the child class I get "The final field birthmark cannot be accessed".
So what's the Java way for this? What am I missing?
You can't do it because while comparing the parent class, the compiler can't be sure that the subclass will initialize it. You'll have to initialize it in the parent's constructor, and have the child call the parent's constructor:
public abstract class Parent {
protected final String birthmark;
protected Parent(String s) {
birthmark = s;
}
}
public class Child extends Parent {
public Child(String s) {
super(s);
...
}
}
Pass it to the parent constructor:
public abstract class Parent {
private final String birthmark;
public Parent(String s) {
birthmark = s;
}
}
public class Child extends Parent {
public Child(String s) {
super(s);
}
}
Another Java-ish way to do this is probably to have the parent class to define an abstract "getter", and have the children implement it. It's not a great way to do it in this case, but it in some cases it can be exactly what you want.
I would do it like this:
public abstract class Parent
{
protected final String birthmark;
protected Parent(final String mark)
{
// only if this makes sense.
if(mark == null)
{
throw new IllegalArgumentException("mark cannot be null");
}
birthmark = mark;
}
}
public class Child
extends Parent
{
public Child(final String s)
{
super(s);
}
}
final means that the variable can be initialized once per instance. The compiler isn't able to make sure that every subclass will provide the assignment to birthmark so it forces the assignment to happen in the constructor of the parent class.
I added the checking for null just to show that you also get the benefit of being able to check the arguments in one place rather than each cosntructor.
Why not delegate initialization to a method. Then override the method in the parent class.
public class Parent {
public final Object x = getValueOfX();
public Object getValueOfX() {
return y;
}
}
public class Child {
#Override
public Object getValueOfX() {
// whatever ...
}
}
This should allow custom initialization.
Yes, the final members are to be assigned in the class in which they are declared. You need to add a constructor with a String argument to Parent.
Declare a constructor in the superclass that's called by the subclass.
You must set the field in the superclass to make sure it's initialized, or the compiler can't be sure the field is initialized.
You probably want to have a Parent(String birthmark) constructor so that you can ensure in your Parent class that final is always initialized. Then you can call super(birthmark) from your Child() constructor.

Categories

Resources