Inheritance with this and super - java

Working in Java.
I have an abstract class as such:
public abstract class Foo {
protected Logger log = null;
// other stuff
public boolean isLoggerSet() {
return (this.log != null) ? true : false;
}
}
Now i extend this class as such:
public class Bar extends Foo {
public Bar() {
this.log = Logger.getLogger(Bar.class);
}
public void someMethod(String[] args) {
Bar b = new Bar();
if(b.isLoggerSet()) {
// do some stuff
}
}
}
The question: Is my Bar.class actually referring to the super.log even though I call this.log since Bar does not have it's own local variable called log? Or would the correct way to implement the isLoggerSet() method be to make it abstract and force Bar.class to implement it itself on it's local copy of log since it's been extended?
Basically I have to say this.log in my Foo class because, it refers to itself. But in Bar class I want to be able to null check log, should I instead be using super.log = in Bar.class?

You have not set your Logger to static, but instead to protected.
Whether you use super or this, they point to the exact same variable in this case.

If there's only one attribute called log in the class hierarchy, it doesn't matter if you say this.log or super.log, it'll refer to the same one - the only one!

this.log is the same super.log. There is only one variable because log is inherited from Foo.
The only one change is required: this.isLoggerSet() should be replaced by b.isLoggerSet()
You cannot call non static method inside static method

Classes are blueprints for making objects. In your case, the blueprint for "Bar" adds on to the blueprint defined in "Foo" (which adds to the blueprint defined in "Object").
Don't let the baseclass confuse you: conceptually here the compiler pulls all the base classes up into one top-level combined class (ignoring the "Object" base):
public class Bar {
protected Logger log = null;
public boolean isLoggerSet() {
return (log != null) ? true : false;
}
public Bar() {
log = Logger.getLogger(Bar.class);
}
public void someMethod(String [] args) {
Bar b = new Bar();
if(b.isLoggerSet()) {
// do some stuff
}
}
}
You would exercise your code like this:
Bar x = new Bar();
x.isLoggerSet(); // Returns true since Bar() constructor just set it
x.someMethod(args);
The first line creates a new object of type "Bar" in memory. This object has a single pointer to a "Logger" object that gets set in the Bar constructor on the first line with "new Bar()".
The next line checks "isLoggerSet". Assuming that "getLogger" returns a live object then the "isLoggerSet" will always return true.
The last line calls "x.someMethod(args)". This method creates a new "Bar" object (whose constructor sets its "log" pointer). Thus the "b.isLoggerSet()" will pass here too.

Here is a slightly modified example:
public abstract class Foo {
protected String name;
public Foo() {
name = "Mr. Foo";
}
}
public class Bar extends Foo {
protected String name;
public Bar() {
name = "Mr. Bar";
}
public void someMethod() {
System.out.println("this.name=" + this.name);
System.out.println("super.name=" + super.name);
}
public static void main(String[] args) {
Bar bar = new Bar();
bar.someMethod();
}
}
Output:
this.name=Mr. Bar
super.name=Mr. Foo
So there are two variables called 'name', one in each class. To access the one in the superclass from within the subclass you need to use 'super.name'.
When creating a Bar() Java checks for a super(...) call to a constructor of the superclass as the first line of the constructor. If it is not there (like above) then 'super();' is invisibly inserted as the first line of the constructor. So I could have written:
....
public Bar() {
super();
name = "Mr. Bar";
}
....
With the same result. However, this is not necessary, Java inserts a super call to the default constructor for you if you don't call a super constructor yourself. In this way constructor chaining is enforced.
If you want to call a super constructor yourself you could also call a non-default constructor, for example:
public abstract class Foo {
protected String name;
public Foo() {
name = "Mr. Foo";
}
public Foo(String name) {
this.name = name;
}
}
public class Bar extends Foo {
public Bar() {
super("Mr. Bar");
}
public void someMethod() {
System.out.println("this.name=" + this.name);
System.out.println("super.name=" + super.name);
}
public static void main(String[] args) {
Bar bar = new Bar();
bar.someMethod();
}
}
Output:
this.name=Mr. Bar // refers to 'name' inherited from Foo
super.name=Mr. Bar // refers to 'name' in superclass, set by the String constructor
// so these both refer to the same variable in this example
Note the default constructor of Foo is not called in this last example.

Related

Effects of java super class call

I'm new to Java and I'm having problems with some OOP, mostly inheritance, concepts.
Consider these two classes:
public class Foo() {
protected String rawData;
public String getSomething(String rawData) {
// ...
this.rawData = rawData;
prepareData();
return rawData;
}
protected void prepareData() {
// do something with class rawData
}
}
public class Bar() extends Foo {
#Override
public String getSomething(String rawData) {
// ...
return super.rawData;
}
#Override
protected void prepareData() {
// do something with class rawData too
}
}
Calling Bar class getSomething() method will lead me to a call of Foo class prepareData()?
Only if your override calls the base method.
Other than base class constructors, Java does not silently call methods for you.
Java always goes deeper even without #Override.
If you don't override the base method it will run it.
If you are in Bar and you want to run Foo method, you can use super.prepareData() in Bar - It will be use when you want to run the super method and add something to it.

Can you override a base class's method in an object of an anonymous type in VB.Net?

Just that:
Is it possible to create an object of an anonymous type that can override a method of its base class in VB.NET?
E.g., in Java we can do:
public class Foo {
public static Foo bar = new Foo() {
#Override
public void doStuff(){
System.out.println("Look, I'm doing stuff!");
}
};
public void doStuff() {
//do nothing
}
public static void main(String[] args) {
Foo.bar.doStuff();
}
}
//Output:
//Look, I'm doing stuff!
Is this possible in VB.NET?
Looks like you can imitate most of this functionality by declaring the method to be overridden as a delegate function that is a property of the class.
For example:
Public Class Foo
Public ReadOnly doStuff As delDoStuff
Delegate Sub delDoStuff()
Private Sub New(del As delDoStuff)
Me.doStuff = del
End Sub
Public Shared bar As New Foo(AddressOf barDoStuff)
Private Sub barDoStuff
WL("Look, I'm doing stuff!")
End Sub
End Class
Anyone have a better way?

Static Factories Methods

One advantage of static factories method states that:
Unlike constructors they can return an object of any subtype of their return type which gives you great flexibility in choosing the class of returned object.
What does this mean exactly?
Can someone explain this with code?
public class Foo {
public Foo() {
// If this is called by someone saying "new Foo()", I must be a Foo.
}
}
public class Bar extends Foo {
public Bar() {
// If this is called by someone saying "new Bar()", I must be a Bar.
}
}
public class FooFactory {
public static Foo buildAFoo() {
// This method can return either a Foo, a Bar,
// or anything else that extends Foo.
}
}
Let me break your question in two parts
(1) Unlike constructors they can return an object of any subtype of their return type (2) which gives you great flexibility in choosing the class of returned object.Let say You have two classes Extended from Player which are PlayerWithBall and PlayerWithoutBall
public class Player{
public Player(boolean withOrWithout){
//...
}
}
//...
// What exactly does this mean?
Player player = new Player(true);
// You should look the documentation to be sure.
// Even if you remember that the boolean has something to do with a Ball
// you might not remember whether it specified withBall or withoutBall.
to
public class PlayerFactory{
public static Player createWithBall(){
//...
}
public static Player createWithoutBall(){
//...
}
}
// ...
//Now its on your desire , what you want :)
Foo foo = Foo.createWithBall(); //or createWithoutBall();
Here you get the both answers Flexability and unlike constructor behaviour
Now You can see through these factory methods its upto you that WHICH TYPE OF PLAYER YOU NEED

How to implement constructor wrapping in Java?

This is what I'm trying to do (in Java 1.6):
public class Foo {
public Foo() {
Bar b = new Bar();
b.setSomeData();
b.doSomethingElse();
this(b);
}
public Foo(Bar b) {
// ...
}
}
Compiler says:
call to this must be first statement in constructor
Is there any workaround?
You could implement it like this:
public class Foo {
public Foo() {
this(makeBar());
}
public Foo(Bar b) {
// ...
}
private static Bar makeBar() {
Bar b = new Bar();
b.setSomeData();
b.doSomethingElse();
return b;
}
}
The makeBar method should be static, since the object corresponding to this is not available at the point you are calling the method.
By the way, this approach has the advantage that it does pass a fully initialized Bar object to the Foo(Bar). (#RonU notes that his approach does not. That of course means that his Foo(Bar) constructor cannot assume that its Foo argument is in its final state. This can be problematical.)
Finally, I agree that a static factory method is a good alternative to this approach.
You can implement the "default constructor" as a static factory method:
public class Foo {
public static Foo createFooWithDefaultBar() {
Bar b = new Bar();
b.setSomeData();
b.doSomethingElse();
return new Foo(b);
}
public Foo(Bar b) {
// ...
}
}
Like it says, a call to this() must be the first thing to happen in a constructor. Is there any reason this wouldn't work?
public class Foo {
public Foo() {
this(new Bar());
Bar b = getBar();
b.setSomeData();
b.doSomethingElse();
}
public Foo(Bar b) {
// ...
}
}

InstantiationException on newInstance of generated anonymous class

Update: this is more-or-less a dupe, and it turns out to be compiler magic adding a constructor to pass in the local variable in build2.
Given an interface like such:
public interface IFoo {
public int get();
}
The code below prints 1, 1, 2 and then throws an exception when trying to call getClass().newInstance() on the value returned by build2, but does not when calling the same on the returned value of build1. Any ideas why?
public class Foo {
public static IFoo build1() {
return new IFoo() { public int get() { return 1; } };
}
public static IFoo build2(final int v) {
return new IFoo() { public int get() {return v;} };
}
public static void main(String[] args) throws Exception {
IFoo foo, bar;
foo = build1();
System.out.println(foo.get());
bar = foo.getClass().newInstance();
System.out.println(bar.get());
foo = build2(2);
System.out.println(foo.get());
bar = foo.getClass().newInstance();
System.out.println(bar.get());
}
}
My debugger indicates that in the newInstance() call, getConstructor0 is throwing a NoSuchMethodException.
Here's what happens:
newInstance() requires a nullary constructor
when you create an anonymous class that is accessing a final variable, a field is actually implicitly created to hold this value, which is initially passed to its implicit constructor
thus, the IFoo created in build2 does NOT actually have a nullary constructor
Here's a snippet to show what's going on:
import java.lang.reflect.*;
public class Foo {
interface IFoo { public int get(); }
public static IFoo build2(final int v) {
return new IFoo() { public int get() {return v;} };
}
public static void main(String[] args) throws Exception {
Class<?> klazz = build2(42).getClass();
for (Constructor<?> c : klazz.getDeclaredConstructors()) {
System.out.println(c);
}
// prints: Foo$1(int)
}
}
It shows that Foo$1 (the assigned binary name for the anonymous IFoo class) has only one constructor, and it takes an int. This is how it can return v, because what's returned is actually whatever is assigned to the implicitly created field by this implicitly created constructor.
It is instructive to decompile the Foo$1 (using e.g. javap -c) to see what bytecode gets generated. You will see that in fact this is what happens when a final variable is accessed by an anonymous class.
Related questions
Why am I having this InstantiationException in Java when accessing final local variables?

Categories

Resources