Define identical treatment of private subclass members in superclass - java

I've got this parent class:
abstract class Parent {
abstract int getX();
}
And two different subclass implementations:
class AgnosticChild extends Parent {
private int x = 5;
#Override
int getX() {
return x;
}
}
class ManipulativeChild extends Parent {
private static int x = 5;
ManipulativeChild() {
x++;
}
#Override
int getX() {
return x;
}
}
Both getX() implementations are identical. Is there any way to get rid of this redundancy while keeping the different implementations for x? Assume that the getX() implementation is a lot more elaborate in practice.

No, the two implementations are not identical - one accesses a static field, and the other accesses an instance field. So although they look identical, they're functionally very different; and there's no opportunity for re-use here, without changing the behaviour of your classes.

You could pull up the int variable to Parent class and implement getX method there
abstract class Parent {
private int x;
public Parent(int x) {
this.x = x;
}
public int getX() {
return x;
}
}
class AgnosticChild extends Parent {
public AgnosticChild() {
super(5);
}
}
class ManipulativeChild extends Parent {
ManipulativeChild() {
super(6);
}
}
Update: The upper code snippet only equal to your code if you want to declare the x in ManipulativeChild as non-static field. Otherwise these are two different implementation and cannot be refactored in the proposed way.

Related

Create object from Class instance

I want to create objects from different classes extending the same class. Can you explain how it will work. Examples would be nice.
Thank you.
class MainClass{
private <T extends DataPoint> void someMethod(Class<T> clazz) {
new clazz(2,3);//<-- create object of class (did not work)
}
private void anotherClass(){
someMethod(GreenDataPoint.class);
someMethod(BlueDataPoint.class);
}
}
class DataPoint {
int x;
int y;
DataPoint(int x, int y) {
this.x = x;
this.y = y;
}
}
class BlueDataPoint extends DataPoint {BlueDataPoint(int x, int y){super(x,y);...}}
class GreenDataPoint extends DataPoint {GreenDataPoint (int x, int y){super(x,y);...}
It looks like you want to create an instance of a dynamically selected class. Obtain a constructor with getConstructor(), and invoke it with the necessary arguments. The Class object has a newInstance() method which is almost the same, but using a Constructor will report any errors in a manner more consistent with other reflective methods.
Constructor<T> ctor = clazz.getConstructor(Integer.TYPE, Integer.TYPE);
T point = ctor.newInstance(2, 3);
Instead of
new clazz();
try
clazz.newInstance();
Good luck

Java equivalent of instance initializer called after constructor

I've been reading about instance initializers in Java, and it's been explained that code common to all constructors can be put into them because they are called every time a new instance of a class is created. Is there an equivalent of instance initializers that run after constructors, for code that would be common to all constructors, but depends on what happens in the constructors?
No, there isn't an exact equivalent. If you want to run some common code, you can always factor out a method and call it at the end of all your constructors:
public class C {
private int x = 5;
private String y;
public C(int x) {
this.x = x;
endConstructor();
}
public C(String x) {
this.x = x.length;
endConstructor();
}
private void endConstructor() {
y = x + "!";
}
}
Sometimes, what seems like a situation where you want to call the same code at the "end" of all constructors can be refactored so that this code is in a single main constructor. Then, all other constructors call it using this(). For the example above:
public class C {
private int x = 5;
private String y;
public C(int x) {
this.x = x;
y = x + "!";
}
public C(String x) {
this(x.length);
}
}
The main constructor can be private, if appropriate.
Something like the #PostConstruct annotation can be used.
If your class has its dependencies injected using setter methods, then its constructor won't fully initialize an instance. Thus, additional "initializations" need to be performed after all the setter methods have been called.
If you think something happens in constructor:
class X {
private int x;
public X() {
// Code that sets x
// =-=-= HERE =-=-=
}
}
Insert the code you want to happen after the constructor... At the end of constructor.
If you have many constructors and don't want to duplicate code:
class X {
private int x;
public X() {
// Code that sets x
init();
}
public X(int x2) {
x = x2;
init();
}
private void init() {
// =-=-= HERE =-=-=
}
}
If every constructor invokes init, we may say this is invoked as a part of constructor, not after it. Imagine a train with one additional car following it, 50cm from it. Both have the same destination/time. Why couldn't we connect the train with standalone car?

Getting duplicate fields when setting from Concrete class

I need to define constant values in each ConcreteClass that extends AbstractClass. For some reason object ends up having duplicate fields, one set of fields is equal to zeros, next one has proper values.
SomeInterface
public interface SomeInterface{
double calculate();
}
AbstractClass
public abstract class AbstractClass implements SomeInterface{
double x, y;
public double calculate(){
return x*y;
}
}
ConcreteClass
public class ConcreteClass extends AbstractClass{
final double x = 1.1;
public setY(double y){
this.y = y;
}
}
I need my concrete class to store constant value final double x = 1.1; while inheriting the calculate() method implementation from abstract class.
You have declared x twice, so you get two x variables; one masks the other. It's doing what you told it to.
To have the concrete class set a value, put the setting of it in a (or all) constructor(s) of the ConcreteClass. Don't declare it again.
I don't know a way that you can declare it final and still alter it in a subclass.
You may be able to do something like this to get around - even though you cannot override instance variables in java.
If all you want to do is have Concrete class's have a constant variable, and the base abstract class use that for calculate method - You could try something like this..
public abstract class AbstractClass implements SomeInterface{
double x, y;
public void setX(double x){
this.x = x;
}
public double calculate(){
return x*y;
}
}
Then in the concrete class you could still have the final variable and have that passed in to the abstract class's setter.
public class TestAbstractVariable extends TestAbstract {
{
final double x = 1.1;
setX(x);
}
public void setY(double y){
this.y = y;
}
}
Hope it helps.
Thanks,
paul

defer final value to subclass java

I have a question similar to 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? but which requires a different solution. As in the above case, I want to declare a variable to be Final in the superclass, but I want the subclass to give it the value. What makes my problem different though is that I don't want the value passed in to the subclass, I want the subclass to 'know' its value, so the above solution doesn't work for me. Then I tried to do this:
public class Superclass{
public final int x;
public Superclass(int x){
this.x = x;
}
}
public class Subclass extends Superclass{
public Subclass(){
x = 1;
super(x);
}
}
...which didn't work (the call to super() must be on the first line :/ ). But this is basically the behavior that I want. Is there a good way to do this? Thanks!
You could do
super(1);
so instead of setting x, you are passing the value.
An alternative to the one above:
class Superclass{
public final int x;
public Superclass(int x){
this.x = x;
}
public static Superclass createNew(Integer y) {
return new Superclass(y);
}
public void print() {
System.out.println(this.x);
}
}
class Subclass extends Superclass{
public Subclass(int x) {
super(process(x));
}
public static Integer process(Integer y) {
if (y < 100)
y += 100;
return y;
}
}
I don't have a java compiler handy, but you're attempting to set x = 1 twice in this code.
x = 1;
And
super(x); //==> this.x = x
Do as #Kal said and do super(1), as x = 1 won't work.

Abstract class can't be instantiated but can have constructor - little confusing, please explain [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Why do abstract classes in Java have constructors?
abstract class constructors?
We know abstract class can't be instantiated but on the other hand it can have constructor. Please explain why abstract class can have a constructor ? How compiler handles this situation?
The constructor of an abstract class is used for initializing the abstract class' data members. It is never invoked directly, and the compiler won't allow it. It is always invoked as a part of an instantiation of a concrete subclass.
For example, consider an Animal abstract class:
class Animal {
private int lifeExpectency;
private String name;
private boolean domestic;
public Animal(String name, int lifeExpectancy, boolean domestic) {
this.lifeExpectency = lifeExpectancy;
this.name = name;
this.domestic = domestic;
}
public int getLifeExpectency() {
return lifeExpectency;
}
public String getName() {
return name;
}
public boolean isDomestic() {
return domestic;
}
}
This class takes care of handling all basic animal properties.
It's constructor will be used by subclasses, e.g. :
class Cat extends Animal {
public Cat(String name) {
super(name, 13, true);
}
public void groom() {
}
}
This is probably not the best explanation but here it goes. Abstract classes enforce a contract much like an interface but can also provide implementation. Classes that inherit from the abstract class also inherit the implemented functions and depending on the language you can override the default implementation as needed.
Say you have abstract class A:
abstract class A {
private int x;
public A(int x) {
this.x = x;
}
public int getX() {
return x;
}
}
Notice, that the only way to set x is through the constructor, and then it becomes immutable
Now I have class B that extends A:
class B extends A {
private int y;
public B(int x, int y) {
super(x);
this.y = y;
}
public int getY() {
return y;
}
}
Now B can also set x by using super(x) but it has on top of that an immutable property y.
But you can't call new A(5) since the class is abstract you need to use B or any other child class.
Abstract class can have constructor that can be called in derived classes. So usually constructor is marked as protected in abstract class.

Categories