Avatar billede fredand Forsker
30. november 2005 - 21:01 Der er 18 kommentarer og
2 løsninger

How does this extending work in detail?

Hello!

I got the following code, se below.
My spontanity thought is that it would write out:
Hello!
Since we call myBar.doIt();

But it print out:
My number: 0

So if any one could explain this for me in detail it would be great.

Best regards
Fredrik

public class Foo
{
    public static class Bar
    {
        private int num = 0;

        public void doIt()
        {
            System.out.println( "My number: " + num );
        }
    }
}


public class Bar extends Foo
{
    public void doIt()
    {
        System.out.println( "Hello!" );
    }

    public static void main( String[] args )
    {
          Bar  myBar = new Bar();
          myBar.doIt();
    }
}
Avatar billede arne_v Ekspert
30. november 2005 - 21:04 #1
public void doIt()
        {
            System.out.println( "My number: " + num );
        }

er en metode i Foo.Bar ikke i Foo og dermed ikke i Bar
Avatar billede arne_v Ekspert
30. november 2005 - 21:05 #2
not an answer to your question - but I just wonder what you are trying
to accomplish
Avatar billede fredand Forsker
30. november 2005 - 21:14 #3
Hello!

I got the question at a job interview and I thought the output would be "Hello"

But if I understand you right you agree with me???

But it prints "My number" or am I crazy (Hope not)???

Regards
Fredrik
Avatar billede fredand Forsker
30. november 2005 - 21:28 #4
Have you tried to execute the code?

"er en metode i Foo.Bar ikke i Foo og dermed ikke i Bar"
To me this sounds like this:
    public void doIt()
    {
        System.out.println( "Hello!" );
    }

would be the executed code??? Do you agree? But it is not!!!

/Fredrik
Avatar billede arne_v Ekspert
30. november 2005 - 22:45 #5
yes I tried
Avatar billede arne_v Ekspert
30. november 2005 - 22:50 #6
Foo.Bar og Bar are two different classes

therefore Foo.Bar.doIt and Bar.doIt are 2 different methods

Bar  myBar = new Bar();

are intepreted as:

Foo.Bar  myBar = new Foo.Bar();

[not quite obvious to me]

Noone uses inner classes.

This is a real trick question.
Avatar billede fredand Forsker
01. december 2005 - 07:58 #7
Hello!

I think that is how I think it works to. And in my opinion the output sholud be "Hello!".

Do you agree with me?

But may the reson be because Foo.Bar is static and there for only is located at one place in the memory. Is this a reson that extends and inner class does not apply to ordinary rules?

Very strange!!
Fredrik
Avatar billede fredand Forsker
01. december 2005 - 19:01 #8
Hello!

I changed the code to:
public class Bar //extends Foo
{
    public void doIt()
    {
        System.out.println( "Hello!" );
    }

    public static void main( String[] args )
    {
          Bar  myBar = new Bar();
          myBar.doIt();
      }
}
Of course the output now is "Hello!", since Foo is not involved at all.

I also changed the code to this (I removed the static from the inner class i Foo):
public class Foo
{
    public class Bar
    {
        private int myNum = 0;

        public void doIt()
        {
            System.out.println( "My number: " + myNum );
        }
    }
}

And the Bar back to (with extends Foo):

public class Bar extends Foo
{
    public void doIt()
    {
        System.out.println( "Hello!" );
    }

    public static void main( String[] args )
    {
          Bar  myBar = new Bar();
          myBar.doIt();
      }
}

This gave me this compilation error:
D:\Fredrik\Javalabb\Bar.java:10: non-static variable this cannot be referenced from a static context
          Bar  myBar = new Bar();
                            ^
1 error

Tool completed with exit code 1


Is this a clue??? How ever my opinion is that the code should be able to be compiled. I think the line "Bar  myBar = new Bar();" just refers to Bar, not to Foo.Bar

So if any one could help me out please let me know!!!! I can not sleep well until i understand the explanation of this.

Best regards 
Fredrik
Avatar billede jakoba Nybegynder
02. december 2005 - 04:57 #9
It is about static methods versus methods in an instance of the object

instance methods are always accessed from 'below' whatever supertype the object may be cast to the method you get is from the lowest subtype overrriding that method.

class A {
    void writeIt( String s ) {
        system.out.println( s );
    }
    static void writeIt2( String s ) {
        system.out.println( "no I wont" );
    }
}
class B extends A {
    void writeIt( String s ) {
        system.out.println( "no I wont" );
    }
    static void writeIt2( String s ) {
        system.out.println( "no I wont" );
    }
}
B bObj = new B();
A aObj = (A)bObj;
// now  aObj.writeIt( "x" ) and bObj.writeIt( "x" ) will give the same "no I wont" response. The object was created as a B and tat is where the search for the method start whatever it might be cast to.

But with the static methods it is different static methods are found through the table created for static class proberties when the class was defined. so:
  aObj.writeIt2( "x" );  // writes "x"  as pr definition in A
  bObj.writeIt2( "x" );  // writes "no I wont"  as pr definition in B

Insidentally this also apply to static variables. So general rule is to just not overwrite statics.

regards JakobA
Avatar billede jakoba Nybegynder
02. december 2005 - 05:22 #10
Boo hiss. answer abowe is not to your question at all.

It is about scopes.

the classname of the class you are defining is in the Outer scope to anything declared inside the class

class A {
    static String A = "something";
    static String toString() {
        return "something else";
    }
    // now inhere (and only here inside the class) 'A' is just a string
    // System.out.println( A ); will write "something"
    // and  new A();  will give an error because A is a variable, not a classname.
}
but with the construct they use there actually is a class 'Bar' visible inside the class scope, so  new Bar();  returns a reference to the static class Bar.

nasty bit of coding there. is there an 'obfusciated Java code' competition?  A clear contender.   

regards JakobA
Avatar billede arne_v Ekspert
03. december 2005 - 20:27 #11
There are only one good rule about inner classes: do not use them !

It is not obvious tro me why Bar in main in the original code is considered
a Foo.Bar and not the Bar extending Foo.

But it is and I would avoid that kind of code instead of understanding it.

Unless you need to get certified. Inner classes are part of some of the
certifications.
Avatar billede simonvalter Praktikant
03. december 2005 - 23:36 #12
I have been trying to figure this one out myself but had to turn elsewhere to get the answer.

<paste>
The relevant section of the JLS is in 6.3.1: "A declaration d of a type named n shadows the declarations of any other types named n that are in scope at the point where d occurs throughout the scope of d." In the top-level class Bar, the declaration of Foo.Bar is not in scope at the time that top-level Bar is declared. Therefore top-level Bar does not shadow Foo.Bar. However if we look inside the Foo class, top-level Bar is in scope at the time Foo.Bar is declared. (Bar is a public top-level class in the same package, so it's in scope.) Therefore by the rule quoted above, Foo.Bar shadows top-level Bar.

Normally, the way to access a shadowed name is by using a fully qualified name (i.e. include the packge name).
Unfortunately in your example we can't do that, as the classes are in the default package, which has no name, which means that the qualified name is unfortunately identical to the simple name, which means there is no way to refer to the shadowed top-level Bar instead of Foo.Bar.

If you put these classes in a package, the problem is easily solved:
code:
package simon;

public class Foo {
    public static class Bar {
        private int num = 0;

        public void doIt() {
            System.out.println("My number: " + num);
        }
    }
}

----

package simon;

public class Bar extends Foo {
    public void doIt() {
        System.out.println("Hello!");
    }

    public static void main(String[] args) {
        simon.Bar myBar = new simon.Bar();
        myBar.doIt();
    }
}

Here "simon.Bar" clearly can only refer to top-level Bar. And if we wanted Foo.Bar instead, we could say simon.Foo.Bar, Foo.Bar, or just Bar. (The last would of course be a horrible idea at this point - the compiler would understand, but humans most likely be very confused (as we all have been).)
</paste>
Avatar billede fredand Forsker
04. december 2005 - 11:20 #13
Hello!

Thanks for an very nice explanation but I still got a couple of questions. 

If I am right your answer means that all that happens in this code is depending on the scope or in other words when each of the classes is declared!!

My question then is when does each of the class get declared, in what order does it happens?

My first thought would be in this order:
Foo
Foo.Bar
Bar

Then I would guess
Foo.Bar is over shadowed by Bar (in my oppinion Foo.Bar is in the scope of Bar since Bar extends Foo and Foo must exists before Bar)

How ever it must be the opposite around! When excuting the code I guess the declaration is taken place in this order:
Foo
Bar
Foo.Bar

There for Bar is over shadowed by Foo.Bar

But I can not explain why!!!

JakobA wrote this interesting comment:
but with the construct they use there actually is a class 'Bar' visible inside the class scope, so  new Bar();  returns a reference to the static class Bar.

Perhaps you could explain why a bit further, cause I guess this is the key to everything? In what order, and why, is the scopes taken place?

Simonvalter wrote:
In the top-level class Bar, the declaration of Foo.Bar is not in scope at the time that top-level Bar is declared.

How come? Even If I see it is wrong my guess would be:
Foo
Foo.Bar
Bar

Simonvalter also wrote this interesting comment:
Unfortunately in your example we can't do that, as the classes are in the default package, which has no name, which means that the qualified name is unfortunately identical to the simple name, which means there is no way to refer to the shadowed top-level Bar instead of Foo.Bar.

How is it possible that the names is identical? Is it just in this particular scope in this code or is this a rule:
A static member class inside an class in a package or the default package appears at the same "level" as an other top-level class in the same package or in the default package. CORRECT ME IF I AM WRONG HERE!!


So if you guys could explain why the order of the scopes are like they are it would be great!

Best regards
Fredrik
Avatar billede fredand Forsker
04. december 2005 - 12:26 #14
Hello again!

Would you agree to me if I said this:

Foo.Bar is inside the scope of top-level Bar
Inside the scope of top-level Bar, Foo.Bar is named Bar or Foo.Bar
There for Foo.Bar is initiated instead of top-level Bar because Foo.Bar is shadowing Bar.


The nearest/"most inner" definition of a class name is the valid class!
The nearest/"most inner" definition always shadowing an outer class with the same name!

Then I guess the scope is taken place like:
Bar-scope-start
  Foo-scope-start
    Foo.Bar-scope-start
    Foo.Bar-scope-end
  Foo-scope-end
Bar-scope-end 

Would you agree to the above thought??

Best regards
Fredrik
Avatar billede jakoba Nybegynder
05. december 2005 - 14:45 #15
>> Foo.Bar is inside the scope of top-level Bar
true enough, but it sortof overcomplexifies the situation.

The thing is that the name 'Bar' of 'top-level Bar' is OUTSIDE of the scope it defines. Just like a method name is outside the local scope of the method.

public void faculty(                    // name of method is outside local scope
                      int faculty        //  parameters to method are inside local scope
                    ) {
        // basic scope rule is "first check local scope, if not found extend search to  outer scope(s)"
        // so here in the methods local scope 'faculty' is the int parameter. not the method
        if ( faculty > 0 ) {            //OK testing param value
            return faculty( faculty-1 ) * faculty;  //ERROR method name is shadowed. We cannot see it from here
        } else {
            return 1;
        }
}

and likewise in top-level Bar's local scope the 'Bar' visible is the one defined inside that scope.
Avatar billede fredand Forsker
30. december 2006 - 13:27 #16
Please give svar so I can reward you guys!
Avatar billede arne_v Ekspert
31. december 2006 - 04:31 #17
all 3 or ?
Avatar billede fredand Forsker
31. december 2006 - 14:36 #18
I guess all 3 deservs points.
How ever 10 p is not much but I do appreciate all effort to explain this.

Best best regards to all of you!
Fredrik
Avatar billede simonvalter Praktikant
31. december 2006 - 16:28 #19
ok
Avatar billede arne_v Ekspert
31. december 2006 - 16:34 #20
.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester