Given a class "Bar" that extends class "Foo" which implements interface "DeeDum"
public interface DeeDum {
public String getDee();
public String getDum();
}
public class Foo implements DeeDum {
public String dee = "D";
public String dum;
public String getDee() { return dee; }
public String getDum() { return dum; }
}
public class Bar extends Foo {
public String dee = "DEE";
public String dum = "DUM";
}
Why doesn't this work?
public static Bar mybar = new Bar();
Assert.assertEquals("DEE", mybar.getDee());
Assert.assertEquals("DUM", mybar.getDum());
I get "D" and null instead. In other words, Bar doesn't inherit accessors from Foo, and can't override properties. Somehow calling mybar.getDum() calls a static instance of class Foo and returns the static properties from the parent class. Even if the properties are overridden in the child class! Does that mean that you can't inherit any methods or properties?
I can't wrap my head around it. Why can't Java inherit accessors (and why did they choose such an odd alternative?)
Or am I just doing something wrong?
Actually, I'm seeing something weird and undeterministic still. If you have another class 'Bar' that extends Foo and sets the inherited accessors in an initialization block
While you can set the parent property in the above block, it doesn’t actually create a copy for the child class.
It seems to be a non-deterministic initialization for multiple classes.
So if you have Bar and Baz which both extend foo and have an initialization block, it seems like both inherit the value set by Bar.
public class Bar extends Foo {
{
dee = "dee";
dum = "dum";
}
}
public class Baz extends Foo {
{
dee = "DEE";
dum = "DUM";
}
}
public static Bar bar = new Bar();
public static Baz baz = new Baz();
System.out.println("mybaz: " + mybaz.getDee() + mybaz.getDum()); // DEEDUM
System.out.println("mybar: " + mybar.getDee() + mybar.getDum()); // DEEDUM
but if they're instantiated in a different order, I get:
public static Baz baz = new Baz();
public static Bar bar = new Bar();
System.out.println("mybaz: " + mybaz.getDee() + mybaz.getDum()); // deedum
System.out.println("mybar: " + mybar.getDee() + mybar.getDum()); // deedum
And it comes out still differently if a default is set in the base class Foo.
I think I understand now that the initialization block in Bar and Baz is actually setting Foo::dee and Foo::dum, but why the difference in declaration? Seems "undefined" to me.
The problem is that your duplicate declaration of the members dee and dum of Foo in Bar hides those of Foo. Bar has its own members; those of Foo will never be used by Bar. What you mean is something like
public class Bar extends Foo {
{
dee = "DEE";
dum = "DUM";
}
}
You are hiding the inherited variables with ones defined in the subclass.
public class Bar extends Foo {
public Bar() {
dee = "DEE";
dum = "DUM";
}
}
should work better.
When you call mybar.getDee(), you're calling the method defined in the Foo base class. (That method was inherited by Bar. Otherwise, you wouldn't have been allowed to call it on a Bar instance variable in the first place.) That method returns the value of the dee field, but it's the dee field defined in the Foo class — the class where the method itself was defined. The compiler resolved the reference to the field at the time the method was compiled, in the Foo class.
Some other answers have used the word override to define what you did by declaring a field named dee in Bar, but that's not what happened. You can't override a field because fields aren't virtual. Perhaps you thought they were, though. If there were such a thing as a "virtual field," I too might expect getDee() to return the run-time class's version of the field (the one in Bar) instead of the one that was in scope at the time the method was compiled (Foo's). But that's simply not the way Java (or C#, or C++, or Delphi, or any other language I know of) works. What language are you accustomed to where this would have worked?
Accessor methods themselves (e.g. getDee()) are inherited, but instance variables are not.
If instance variables could be overridden in subclasses (like you're trying to do here), it would cause many more problems than it would fix.
Accessors aren't the problem, it's the fields. The accessors are referring to Foo.this.dee, not to Bar.this.dee which are separate.
As for your second "question"...
Actually, I'm seeing something weird and undeterministic still...
...
"...System.out.println(baz.getDee()); // 'DEE' but would expect 'dee'"
It would be useful if you run the program before posting the question to see actual results.
This is what I get. It is "dee" as you expected.
You could see it for your self by creating the files, compiling them and the run them as shown below:
C:\oreyes\samples\java\dee>type DeeDum.java Foo.java Bar.java Baz.java Test.java
DeeDum.java
public interface DeeDum {
public String getDee();
public String getDum();
}
Foo.java
public class Foo implements DeeDum {
public String dee = "D";
public String dum;
public String getDee() { return dee; }
public String getDum() { return dum; }
}
Bar.java
public class Bar extends Foo {
{
dee = "DEE";
dum = "DUM";
}
}
Baz.java
public class Baz extends Foo {
{
dee = "dee";
dum = "dum";
}
}
Test.java
class Test {
public static Bar bar = new Bar();
public static Baz baz = new Baz();
public static void main( String [] args ) {
System.out.println(bar.getDee()); // 'DEE'
System.out.println(baz.getDee()); // 'DEE' but would expect 'dee'
}
}
C:\oreyes\samples\java\dee>javac *.java
C:\oreyes\samples\java\dee>java Test
DEE
dee
C:\oreyes\samples\java\dee>
PEBKAC?
Related
At work I came across the following design in a java project:
Consider interfaces Foo, Bar, and Baz as follows:
interface Bar { public int a(); }
interface Baz { public int b(); }
interface Foo extends Bar, Baz { public int c(); }
Now, consider class FooImpl:
public class FooImpl implements Foo {
private Bar bar;
private Baz baz;
public int a() {
return bar.a();
}
public int b() {
return baz.b();
}
public int c() {
return 0;
}
}
What are the use cases for this kind of class hierarchy? It seems to me that this introduces a lot of boilerplate and does not add much in terms of abstraction, other than breaking up what could be a large file into smaller files.
It allows things like this:
Foo foo = new FooImpl();
useBar(foo);
public void useBar(Bar bar) {
bar.a();
}
Whether this is useful depends on the real context. Your example code with classes and methods with meaningless names does not support a rational judgement.
The other thing to note is your FooImpl is actually implemented as some kind of wrapper for Bar and Baz instances. That's not (strictly speaking) an interface design issue.
I think it's a workaround for multiple inheritance (which is not allowed in Java). You're not showing implementations for Bar and Baz, but let's suppose they exist:
public class BarImpl implements Bar {
#Override
public int a() {
return 1;
}
}
public class BazImpl implements Baz {
#Override
public int b() {
return 2;
}
}
You neither have told us how Bar and Baz attributes are instantiated and set to FooImpl, because, if executed as stated in your question, you'll get a NullPointerException both in FooImpl.a() and FooImpl.b(). Again, let's imagine how this could be achieved:
public class FooImpl implements Foo {
private Bar bar; // better if final
private Baz baz; // better if final
// Constructor to properly initialize bar and baz
public FooImpl(Bar bar, Baz baz) {
this.bar = bar;
this.baz = baz;
}
#Override
public int a() {
return bar.a();
}
#Override
public int b() {
return baz.b();
}
#Override
public int c() {
return 0;
}
}
Wiring everything up:
Bar bar = new BarImpl();
Baz baz = new BazImpl();
Foo foo = new FooImpl(bar, baz);
int one = foo.bar(); // 1
int two = foo.baz(); // 2
In a way, FooImpl is "inheriting" from both BarImpl and BazImpl, though this is achieved by means of delegation.
To do this is really just redirecting fooimpl using its propertie's(bar and baz) "a" method and "b" method
If I have the following class, Foo, where Bar is also a class:
public class Foo {
private Bar baz;
public Foo() {
}
}
Am I right in thinking that if I initialise baz where it is declared I will have an aggregate relationship between Foo and Bar and if I initialise baz in Foo's constructor I will have a composite relationship? Like this:
Aggregate (I think this is probably incorrect?):
public class Foo {
private Bar baz = new Bar();
public Foo() {
}
}
Composite:
public class Foo {
public Foo() {
baz = new Bar();
}
}
I'm a little new to Java, and seeing as everything is a class, I'm having difficulty visualising how (in particular) the aggregate relationship works unless I make baz static. If I create baz somewhere else and pass it in to the constructor of Foo, then won't baz just be a composite of some other class? Bit confuzzled.
Try reading more about the dependency injection. It's what you describe in your last sentence. Its a pattern that removes hard-coded dependencies as in both of your examples, but this job is delegated to a higher-level authority.
You would get something like:
public class Foo {
private Bar baz;
public Foo(Bar baz) {
this.baz= baz;
}
}
The actual instance of baz can be changed in both compile and runtime.
The actual composition means that class Bar has no meaning (or value) without the class Foo, and it cannot exist without the Foo, - Bar "is a part of" Foo. An example would be: an IMEI number is a part of the phone.
The aggregation tells that Foo only owns the Bar, - Bar "has" Foo. An example would be: a battery is a part of the phone. Other devices that are not phones could also have batteries.
These two concepts don't have much to do with the way you code it.
Composition
final class Car{
private final Engine engine;
Car(EngineSpecs specs) {
engine = new Engine(specs);
}
void move() {
engine.work();
}
}
Aggregation
final class Car {
private Engine engine;
void setEngine(Engine engine) {
this.engine = engine;
}
void move() {
if (engine != null)
engine.work();
}
}
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.
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
Is there a way for a Java class to have an awareness of its instantiator? For example:
public class Foo() {
public Foo() {
// can I get Bar.myInteger from here somehow
// without passing it in to the constructor?
}
}
public class Bar {
private int myInteger;
public Bar() {
myInteger = 0;
Foo foo = new Foo();
}
}
Is there any particular reason you don't want to pass anything in the constructor?
Simply put, this violates the encapsulation principle... and probably several others as well.
With inner classes, you can.
public class Bar {
private int myInteger;
public class Foo() {
public Foo() {
// you can access myInteger
}
}
public Bar() {
myInteger = 0;
Foo foo = new Foo();
}
}
No, you can't.
What are you trying to do?
You can get some information with a stack trace:
Throwable t = new Throwable();
t.fillInStackTrace();
StackTraceElement[] stt = t.getStackTrace();
then explore the elements of stt[].
You cannot access it the way you want to. But using an inner class might be appropriate here, depending on what problem you are trying to solve. The inner class can access private variables of the outer one.
If they're in the same package, you can change the access level of myInteger to protected and Foo can access it directly, but you still need a reference to Bar unless myInteger is also static. I don't like to do that though, it makes them harder to test.
Aside from that, your options are using setters after instantiating the Foo or passing it to the constructor.
You can only access a private member of another class if you either explicitly pass it to the constructor if you provide getter/setter functions. So the answer to your question is no.
You could force "Instantiators" to use a Factory. But in any case, the "identity" of the object requesting a new instance should be passed as a parameter.
And careful in defining what kind of identity you want to trace. An instance ID? a Class ID?
If Foo were an inner class to Bar, it could see Bar's members.
you can work with inner classes, like this:
public class Bar {
private int myInteger;
public Bar() {
myInteger = 0;
Foo foo = new Foo();
}
class Foo {
Foo() {
int i = Bar.this.myInteger;
}
}
}
regards.
Keeping it simple...
1.
If Foo always needs to know myInteger from Bar then pass it into the constructor.
2.
If Foo only occasionally needs to know myInteger then call a setter after the constructor.
If Foo needs more than myInteger, i.e. the whole Bar object then Bar can pass itself in using the "this" keyword.
public class Foo
{
public Foo(Bar bar)
{
//Do something with Bar
}
}
// Somewhere in Bar (in a non-static method)
new Foo(this);