I have
class A {
int var;
public A(int x) {
var = x;
}
}
class B extends A {
int var2;
public B(int x, int y) {
super(...);
var2 = y;
x = f(y);
}
}
For the subclass B, I need to calculate the value x that is used in the constructor of A. If I were free to move super below my x=f(y) then I could pass in the result to the constructor of A (super). But super has to be the first line in the constructor of B.
Is there any way to initialize A with the proper value the first time? What if A.var were final and i couldn't go back and change it after construction?
Sure, I could put super(f(y)), but I could imagine cases where this would become difficult.
Assuming var is private and you need to set the value with the constructor (which seems to be the point of the question, otherwise there are many easy solutions), I would just do it with a static factory-like method.
class B extends A {
int var2;
public static B createB(int x, int y) {
x = f(y);
return new B(x, y);
}
public B(x, y) {
super(x);
this.var2 = y;
}
}
something like that. You have no choice, as explicit constructor invocation must happen on the first line of the wrapping constructor.
You can do it like this :
class B extends A {
int var2;
public B(int x, int y) {
super(calculateX(y));
var2 = y;
}
private static int calculateX(int y) {
return y;
}
}
Calling a static method is the only thing you can do before calling the superclass constructor.
Alternative to hvgotcodes, since it looks like you also want to set A's variable...
class B extends A {
int var2;
public B(int x, int y) {
super(x);
var2 = y;
x = f(y);
super.var = ...;
}
}
Another approach could be to add a protected constructor without parameters to A that relies on lazy initialization:
class A {
int var;
public A(int x) {
var = x;
}
/**
* Just use this constructor if you initialize var
*/
protected A(int x) {
}
}
class B extends A {
int var2;
public B(int x, int y) {
super();
var2 = y;
var = f(y);
}
}
But that's hard to document, not very obvious to team members and shouldn't be used for an api.
Related
I was asked this question in one of the tests:
class A{
int i;
public A(int x){this.i = x;}
}
class B extends A{
int j;
public B(int x, int y){
super(x);
this.j = y;
}
}
Given the following code, which of the constructors shown in the options can be added to class B without causing compilation to fail?
Options:
B() {}
B(int y){ j = y; }
B(int y) { super(y*2); j=y; }
B(int y) { i=y; j=y*2; }
B(int z) { this(z,z); }
What should be the answer?
I tried searching for it but want to know the reasoning behind the correct answer.
I tried searching for it but want to know the reasoning behind the
correct answer.
From source one can read:
Note: If a constructor does not explicitly invoke a superclass
constructor, the Java compiler automatically inserts a call to the
no-argument constructor of the superclass. If the super class does not
have a no-argument constructor, you will get a compile-time error.
Object does have such a constructor, so if Object is the only
superclass, there is no problem.
Let us go through each option one by one:
1- B() {} No, because class A does not have no default constructor;
2- B(int y){ j = y; }, No for the same reason a 1);
3- B(int y) { super(y*2); j=y; }. Valid, this one explicitly invokes super with a valid constructor;
4- B(int y) { i=y; j=y*2; } No, for the same reason as 1) and 2);
5- B(int z) { this(z,z); }. Valid, this one calls the constructor :
public B(int x, int y){
super(x);
this.j = y;
}
which explicitly invokes super with a valid constructor.
If class A was instead :
class A{
int i;
public A(){}
public A(int x){this.i = x;}
}
because now class A has explicitly the default constructor all options would be valid.
Iam beginner in programming iam struct at how to call parameterised constructor presented in base class.
My code:
public class base {
int a, b;
base(int x) {
a = x;
System.out.println(a);
}
static class derived extends base {
derived(int y) {
b = y;
System.out.println(b);
}
}
public static void main(String[] args) {
derived de = new derived(10);
}
}
super(int) refers to base(int x):
derived(int y) {
super(DEFAULT_VALUE_FOR_A);
b = y;
System.out.println(b);
}
where DEFAULT_VALUE_FOR_A is an int value to initialise the field a from base.
Please, follow the Java naming convention, your code is hard to read. The first letter of the class name should be capitalized.
When ever you creates object of any class constructor of parent is also called
In your case derived de = new derived(10); Will call base() in derived(int y) ..
Either add default constructor in base class or call parametarized constructor form base
public class Base {
int a, b;
Base(){} // if you remove this please add super(0) in Derived(int y)
Base(int x) {
a = x;
System.out.println(a);
}
static class Derived extends Base {
Derived(int y) {
// super(0); // uncomment this if you dont want to add default constructor in your parent class
b = y;
System.out.println(b);
}
}
public static void main(String[] args) {
Derived de = new Derived(10);
}
}
In Java I could create a class and initialize a variable without a constructor:
public class Foo {
private int x = 1;
public getx() {
return x;
}
}
But in c++, to accomplish the same thing, the only way I know how is to do this:
class Foo
{
private:
int x;
public:
Foo()
{
x = 1;
}
getx()
{
return x;
}
};
Since C++11 you can do this. In other words, this works pretty well:
class Foo
{
int x = 1;
public:
int getX() { return x;}
};
Consider following class:
class Foo
{
private class Bar
{
int operatedNumber;
Bar(int x, int y)
{
operatedNumber = operate(x,y);
}
int operate(int x)
{
return x*2;
}
}
public int operate(int x, int y)
{
return x+y;
}
public Foo()
{
Bar b = new Bar(3,5);
}
}
I am getting compile time error The method operate() is not applicable for the arguments (int, int).
Is there a way to call the second operate() function?
Is there a way to call the second operate() function?
Yes - you can qualify it with Foo.this to refer to the enclosing instance of Foo:
operatedNumber = Foo.this.operate(x,y);
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.