Java: Why could base class method call a non-exist method? - java

class BaseClass {
private void f() {
System.out.println("Baseclass f()");
}
public static void main(String[] args) {
BaseClass dc = new DerivedClass();
dc.f();
}
}
class DerivedClass extends BaseClass {
public void f() {
System.out.println("DerivedClass f()");
}
}
In my opinion, the object dc refers to should have only one non-override method - public void f() method,which make it(the public method) invisible when refered to with BaseClass reference.Since the object dc referes to does not have the private void f() method either because the DeriverClass could not inherit the private method,how could the object dc refers to call method f()?
thanks.

A common(ish) misconception is that private is per instance rather than per class.
For example:
class Foo
{
private int a;
public bar(final Foo other)
{
other.a = 5;
}
}
Some people are under the impression that the code above should not work because "a" is "private". That is not the case, any Foo instance can access the private variables/methods of any other Foo instance. "private" just means that instances of other classes (other than Foo in this case) cannot access the private members.

Just to keep things straight, DerivedClass (DC) DOES inherit private void f() from BaseClass (BC). This inherited method is not accessible to DC but it is there because any method called in the BC part of DC has to have access to all of BC. So when you cast DC to a BC the inherited method becomes available. Now because you are running the code inside of the BC class it can access all of the private members of BC. If you moved the main to DC it shouldn't compile let alone run.

Four points:
(1) To elaborate on what vivyzer wrote, the code compiles because the main method in BaseClass has access to the class's own private methods. If you wrote the code as:
class BaseClass {
private void f() { }
}
class DerivedClass {
public void f() { }
}
class Bystander {
public static void main() {
BaseClass inst = new DerivedClass();
inst.f();
}
}
Then the code would not compile.
(2) This is allowed by the language to support the usecase where the author of a base class can add a new private method without worrying about other authors' derived types.
(3) You won't see this if the method was not private. If the base class's f() had package or protected visibility, then the method would be a virtual method.
(4) The reverse of point #2 is not supported by Java. Specifically, if a derived class has a private method, and a new version of the base type introduces a non-private method with the same signature, the derived class and new base class cannot be used together. There are other languages (for example C#) that addresses these sorts of modular, generational development questions more completely. If you are interested in this aspect, this is a good read on Artima: Versioning, Virtual, and Override

The main method is inside BaseClass and the private methods are visible to it. If main is in some other class, it will not compile.

Related

How to force my subclass constructor not to call base class constructor?

public class Base {
public Base() {
foo();
}
public void foo() {
System.out.println("Base.foo()");
}
}
public class Derived extends Base {
public Derived () {}
public void foo() {
System.out.println("Derived.foo()");
}
}
And then, when i call those:
public class Running {
public static void main(String[] args) {
Base b = new Base();
Derived d = new Derived();
}
}
It outputs:
*Base.foo()*
*Derived.foo()*
So why, when it gets to derived constructor, it invokes the base constructor but uses the derived's method instead?
PS: If I mark those methods as private, it will print out:
*Base.foo()*
*Base.foo()*
This is how Java works read this page https://docs.oracle.com/javase/tutorial/java/IandI/super.html
And more specifically the Note here :
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.
So as you can see this is expected behavior. Even though you dot have a super call it is still automatically inserting it.
In regards of the second Question even though you are within the super constructor body still you Instance is of the Subtype. Also if you have some familiarity with C++ read this Can you write virtual functions / methods in Java?
The reason why it will write the base class when marking with private is because private methods are not Inherited. This is part of the Inheritance in Java topic.
To answer the question in your title. As I said, you cannot avoid the base class constructor being called (or one of the base class constructors if it has more than one). You can of course easily avoid the body of the constructor being executed. For example like this:
public class Base {
public Base(boolean executeConstructorBody) {
if (executeConstructorBody) {
foo();
}
}
public void foo() {
System.out.println("Base.foo()");
}
}
public class Derived extends Base {
public Derived() {
super(false);
}
public void foo() {
System.out.println("Derived.foo()");
}
}
public class Running {
public static void main(String[] args) {
Base b = new Base(true);
Derived d = new Derived();
}
}
Now the main method prints only:
Base.foo()
Because in the contructor of the Derived class it automatically gets injected a call to super(), if you do not add a call to super or to other constructor in the same class (using this).

Why protected access modifier works differently when it's used along with static from that used with non static

Normally it is said that when we are using protected for a field in a class then its subclass cannot access it using a reference of the Base Class given that the subclass is in a different package . That is true . But I found that it behaves differently when a static keyword is added with the field . It becomes accessible . How is it possible . Is any one having the answer .
package com.car;
public class Car {
static protected int carNo=10;
}
package com.bmw;
import com.car.*;
public class BMW extends Car {
public static void main(String[] args) {
//Its accessible here
System.out.println(new Car().carNo);
}
}
6.6.2.1. Access to a protected Member
Let C be the class in which a protected member is declared. Access is
permitted only within the body of a subclass S of C.
In addition, if Id denotes an instance field or instance method, then:
If the access is by a qualified name Q.Id, where Q is an ExpressionName, then the access is permitted if and only if the type
of the expression Q is S or a subclass of S.
If the access is by a field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .),
where E is a Primary expression, then the access is permitted if and
only if the type of E is S or a subclass of S.
Source : https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6.2.1
see
public class BMW extends Car {
public static void main(String[] args) {
System.out.println(new BMW().carNo);
}
}
is valid because new BMW() is a subclass of Car, even being in a different package.
public class BMW extends Car {
public static void main(String[] args) {
System.out.println(new Car().carNo);
}
}
is not valid because new Car() is not a subclass of Car, and it's being called in a different package. (see Java: Is a class a subclass of itself? for a discussion if a class is subclass of itself)
Now, if carNo is static, this is legal
System.out.println(new Car().carNo);
However, the right syntax here would be
System.out.println(Car.carNo);
because carNo is not an instance field, since it's static. In fact, even this will work from inside BMW
System.out.println(carNo);
because
Only members of a class that are declared protected or public are inherited by subclasses declared in a package other than the one in
which the class is declared
as stated at https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.2
The main method is in BMW, that is a subclass of Car. Thus, it has access to the protected variable.
The reason it was not visible before was because static methods, like main, cannot access non-static variables. Once both criterias are fullfilled, the main method can access it.
class Car {
protected int a = 9;
}
class BMW extends Car{
public static void main(String[] args) {
int b = a; // cannot make a static reference to a non static field warning error shown by eclipse
}
}
Two ways to remove it:
either make a static
class Car {
protected static int a = 9;
}
class BMW extends Car{
public static void main(String[] args) {
int b = a; // cannot make a static reference to a non static field
}
}
or call it outside main in a non static method, main being static cannot call to class variables
class Car {
protected static int a = 9;
}
class BMW extends Car{
public void m() {
int b = a;
}
public static void main(String[] args) {
}
}
You are mixing two concepts here:
1) accessing static variables from non-static context
2) protected access modifier
in java you can access protected members through inheritance or only within the same package.
Try accessing noCar here:
class Car{
int noCar = 9;
public static void main(String[] args) {
int b = noCar; // cannot make a static reference to a non static field warning error shown by eclipse
}
}
EDIT: considering packages
package com.bmw;
import com.car.*;
public class BMW extends Car {
public static void main(String[] args) {
System.out.println(new BMW().carNo);
Car car = new Car();
// Car has no idea that BMW is the child class
// and since it is not public we cannot access it directly
//can be accessed like this
car.getCarNo();
// you can do this because BMW has the variable carNo because of it extending Car
BMW bmw = new BMW();
int a = bmw.carNo;
}
}
package com.car;
public class Car {
protected int carNo=10;
public int getCarNo() {
return carNo;
}
public void setCarNo(int carNo) {
this.carNo = carNo;
}
}
The reason being the keyword "static".
Static associates the variable with the class and the not the instance. Since the class is public , all it's static variables will also be public i.e. all the variables will be accessible from other classes.
Also BMW extendsCar. Hence it will always be visible to BMW.
Yes, that is weird. In order to shed some light on this behaviour, it may be helpful, first of all, to recap how the protected modifier works in the absence of the static keyword, and why it works the way it does.
If class T declares a protected member m, then T and any class belonging to the same package as T can access the member, i.e. can say t.m; the type of the reference (t) must be T or a subclass of T. Additionally, any subclass U of T outside T's package can say t.m; in this case, the type of t must be U or a subclass of U.
The final part of this statement contains an important restriction. Its motivation is succintly explained in section 3.5 of The Java Programming Language (fourth edition) by Arnold, Gosling and Holmes:
The reasoning behind the restriction is this: Each subclass inherits the contract of the superclass and expands that contract in some way. Suppose that one subclass, as part of its expanded contract, places constraints on the values of protected members of the superclass. If a different subclass could access the protected members of objects of the first subclass then it could manipulate them in a way that would break the first subclass's contract -- and this should not be permissible.
Let's try to better understand this explanation by putting your Car and BMW classes to work. The following is a modified version of Car. I replaced the carNo field with an equally protected, but non-static, color field. The class also declares an obvious public getter/setter pair.
package com.car;
import java.awt.Color;
public class Car {
protected Color color;
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}
Here is the BMW class, which at the moment does nothing but inherit Car's members.
package com.bmw;
import com.car.Car;
public class BMW extends Car {
}
Finally, let's add another subclass of Car.
package com.ferrari;
import com.car.Car;
import java.awt.Color;
public class Ferrari extends Car {
public Ferrari() {
color = Color.RED;
}
#Override
public void setColor(Color color) {
log("Nope. I'm proud of my color.");
}
...
}
As you can see, in our application Ferrari objects show an exclusive preference for a certain color (which is almost true in the real world, too). The color field is set in the constructor, and made read-only by a straightforward override of setColor(). Notice, by the way, that direct access to the color protected member is permitted here because the reference (an implicit this) is of the right type, that of the accessing subclass (Ferrari plays the role of U in the above description).
Now, suppose that BMW objects want to demonstrate their superiority over other cars, so they ask the class's programmer to be enhanced by means of a bold overtake() method. The programmer obliges.
...
public class BMW extends Car {
public void overtake(Car car) {
log("Wow! Become green with envy!");
car.setColor(Color.GREEN);
}
...
}
But, reading the application logs, the programmer soon discovers that, while this works fine with other cars, Ferrari objects stubbornly resist any insolence. He then, urged by BMW objects to find a solution, tries to by-pass the setColor() method...
...
public class BMW extends Car {
public void overtake(Car car) {
log("Wow! Become green with envy!");
car.color = Color.GREEN; // <-
}
...
}
... which is exactly what we can't do in Java. The Ferrari subclass's expanded contract places a constraint on the value of the color protected member. If the BMW subclass could directly access the color field through a Car (or Ferrari) reference, it would be able to break that contract. Java does not allow this.
So, this is why the protected modifier behaves the way it does when applied to non-static members. With protected static members, things change altogether. If the color field were static, any method inside BMW could directly access it. In your code, the BMW class accesses the carNo field without a hitch.
In the example above, the Ferrari class can restrict the possible values of the color field by overriding the instance setColor() method, which effectively amounts to changing, without violating, the superclass's contract.
Now, Java is, by design, a class-based object-oriented language, which does not have a concept of class object in the same sense as, for example, Objective-C. In Objective-C, classes are, literally, objects, and class methods (analogous, but non identical, to Java static methods) are, so to speak, instance methods of the class object -- with all the consequences of this fact: in particular, they can be overridden and used as polymorphic operations, the array class method in NSArray and NSMutableArray being an obvious example.
In Java, there is no class object -- an instance of java.lang.Class is by no means the same thing as an Objective-C class object. Static methods are, in essence, functions with an associated namespace. Most importantly, they can be inherited, but can't be overridden -- only hidden, just like static and non-static fields. (By the way, this means that invoking a static method is more efficient than calling an instance method, because not only its form, but also its implementation can be chosen at compile-time.)
But, and this is the end of the story, if static members cannot be overridden, they cannot really change the superclass's contract either. And, if they cannot change the superclass's contract, a subclass cannot break the contract of a different subclass by only accessing the latter's static members. If we recall that avoiding this kind of violations was precisely the reason of the restriction concerning protected non-static members, we can now understand why the designers of Java ended up lifting that restriction for protected static members. Once again, we can find a concise allusion to this line of thought in a short passage from section 3.5 of The Java Programming Language:
Protected static members can be accessed in any extended class... This is allowed because a subclass can't modify the contract of its static members because it can only hide them, not override them -- hence, there is no danger of another class violating that contract.

What does Java `this` actually refer to in an inheritance situation?

Why does the following Java code produces:
10
superclass
The code in question is:
class SuperClass {
int a;
public SuperClass() {
this.a = 10;
}
private void another_print() {
System.out.println("superclass");
}
public void print() {
System.out.println(this.a);
this.another_print();
}
}
class SubClass extends SuperClass {
int a;
public SubClass() {
this.a = 20;
}
private void another_print() {
System.out.println("subclass");
}
public void print() {
super.print();
}
}
public class Main {
public static void main (String[] args) {
SubClass c = new SubClass();
c.print();
}
}
There is no instance of SuperClass ever created, isn't there?
Not only that Java starts looking for the method to invoke from the SuperClass, it even somehow knows that a = 10!
Let's consider a similar Python code:
class SuperClass:
def __init__(self):
self.a = 10
def another_prn(self):
print('superclass')
def prn(self):
print(self.a)
self.another_prn()
class SubClass(SuperClass):
def __init__(self):
self.a = 20
def another_prn(self):
print('subclass')
def prn(self):
super().prn()
c = SubClass()
c.prn()
It works as I expect:
20
subclass
The only explanation that my colleagues (Python disliking Java folks) came up with is: "Python is not a true OOP language". Not very convincing at all.
Update: private void another_print() is my blunder, I should have used protected.
It is the order of constructor calling in Java.
In the SubClass, when you instantiate c, the constructor implicitly calls the default constructor of the SuperClass (public SuperClass()) (it must do so). Then a is set to be 10 in the SuperClass.
Now that we're done with the SuperClass constructor, we get back to the constructor of SubClass, which assigns a = 20. But fields are not subject to overriding in java, so a in SuperClass is still 10.
After that it's pretty obvious, we call c.print() which calls the print of SubClass, which calls the print of SuperClass (by super.print()), which prints a which is as you remember 10. Then another_print (which is not overridden since it is private) just prints superclass and we're done.
In the sub-class's print you just call super-class's print method.
So it prints the a from the super class of course.
You have two separate a fields here. Fields are not subject to overriding, only methods are. The super-class has an a field and you have another a field in the sub-class.
If another language produces another result, that's not a big surprise. Also, I am not sure your Python code is logically equivalent/analogous to your Java code.
My comment explained the reason your code probably doesn't work as expected.
Below is code written how you most likely expected it to work. Note the comments in the code.
static class SuperClass {
int a; // only declare field in superclass to avoid hiding
public SuperClass() {
this.a = 10;
}
// make method protected, public, or package private to allow children to override it
protected void another_print() {
System.out.println("superclass");
}
public void print() {
System.out.println(this.a);
this.another_print();
}
}
static class SubClass extends SuperClass {
public SubClass() {
this.a = 20;
}
#Override
protected void another_print() {
System.out.println("subclass");
}
public void print() {
super.print();
}
}
public static void main (String[] args) {
SubClass c = new SubClass();
c.print();
}
This will print
20
subclass
I've debugged my slightly corrected code and found out that:
this is an instance of SubClass
Unlike Python, Java is ok with more than one variable of the same name (as peter.petrov mentioned in his answer, but I didn't got it right away)
One of the as is from the SubClass and the second is from the SuperClass (as implicit superclass constructor call, again unlike Python)
this.a has a different value in test_super() and test_sub() and that is the magic, given that this is a SubClass and Java documentation reads:
this is a reference to the current object — the object whose method or constructor is being called
I think I can live with the fact that this will have all the variables from the whole dependency tree and Java will select which one to use depending on the context.

inner class have access to private final methods in base class but why?

Why creators of java allowed this situation? I am sure there must be some reason for it. My below code allows Lion to mischievously run as fast as Cheetah.
public class animal {
class carnivores {
private final void runAsFastAsCheetah() {
System.out.println("Ran as fast as Cheetah");
}
}
public class Lion extends carnivores {
public void runAsFastAsLion() {
System.out.println("Ran as fast as Lion.");
super.runAsFastAsCheetah();
}
}
public static void main(String[] args) {
animal animal = new animal();
Lion lion = animal.new Lion();
//lion.runAsFastAsCheetah(); //Not allowed but//
lion.runAsFastAsLion();
}
}
EDIT: For those taking Lion and cheetah seriously, I have modified code.
public class foo {
class A {
private final void myMethod() {
System.out.println("in private final myMethod()");
}
}
public class B extends A {
public void myMethod() {
System.out.println("in B's myMethod()");
super.myMethod();
}
}
public static void main(String[] args) {
foo foo = new foo();
B b = foo.new B();
b.myMethod();
}
}
All classes with the same outer class can access private members of any other class of the same outer. This features was added when nested classes were added. IMHO this was because these members are compiled together and it makes nested classes more useful.
Note: The JVM doesn't support this feature, and thus the compiler add accessor methods which appear the the stack traces like access$100. These are added by the compiler to allow access to private members between classes.
Access modifiers only check one level. If A can access B and B and access C, then A can access anything B lets it access which could be C.
The reason this is don't is to avoid making private meaningless. If a private member could only be accessed by class which could access it, it would mean it could only be called by a main in the same class. This would make it useless in any other class.
From the Java Language Specification:
A member (class, interface, field, or method) of a reference type, or
a constructor of a class type, is accessible only if the type is
accessible and the member or constructor is declared to permit access:
...
Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the
top level class (§7.6) that encloses the declaration of the member or
constructor.
In other words, within a top-level class, private and protected no longer apply.
As for the why, well if you think of everything in a class being accessible by that class, then that includes everything inside any inner classes too!

Java inheritance: Reducing visibility in a constructor vs inherited method

In the following code, the constructor of Child has reduced visibility from public to private, which is allowed. The inherited methods, such as test(), cannot have reduced visibility. Why does Java operate this way?
class Parent {
public Parent(){}
public void test()
{
System.out.print("parent test executed!");
}
}
class Child extends Parent{
private Child(){}
private void test(){
System.out.print("child test executed!");
}
}
Constructors are not inherited, so Child() doesn't override Parent().
As for the methods, if you have (if Child() were public)
Parent p = new Child();
p.test();
Had it been allowed, this would be invoking a private method. So narrowing the access while overriding is not permitted.
When extending a class you are stating that your class is an extension of the parent class ("IS-A" relationship). What this means is that your class will have all methods of your parent class. This is the same as implementing an interface in java except you gain the method definitions (and fields) from your parent and not just methods declared in the interface. In interfaces constructors are not present because they are not methods. Constructors are special as they belong entirely to the class they are declared on. They declare how to construct only themselves.
In order to construct an object you must know that objects class.
class A {
private message;
private A() {
message = "You created an A";
}
public A(String message) {
this.message = message;
}
public void printMessage() {
System.out.println(message);
}
public static A createAnA() {
return new A();
}
}
class B extends A {
public B() {
super("You created a B");
}
}
A anA = new B(); // This will work
A anotherA = new A(); // This is not allowed as the constructor is private
A yetAnotherA = A.createAnA(); // This works too
So when we constructed B we can say that it is an A. Even though the constructor A is private this is due the constructor not being a part of the interface. The only thing we are saying about B when we assign it to a field of type A is that it has the methods of declared in A. In this case printMessage and createAnA.
That is why you can make the constructor private without changing the definition of the class. Now, why are you not allowed to make the method private when overriding a parents signature. This comes to having varying definitions of the [class].method(). Let's say that you could make your method private. Let's say that you declared a printMssage in the B class. Your reasoning is that you want that method for your use only inside the method and you want your parents printMessage to be used when called externally. Now, you wrote a method like this in the B class.
public void adjustMessage(String additional) {
message = getMessage() + additional();
}
Which version of get message would be executed? Your private one or the public one of your parents? The Java dispatcher would of course choose the public one as it is the one declared in the interface. So we we look at this example we can see if you did make your method have different a lower privilege your method could never be dispatched too which would just make things confusing for the reader.
This is a very good question.

Categories

Resources