Inheritance of private methods [duplicate] - java

Here's an interesting code snippet:
public class Superclass {
public static void main (String[] args){
Superclass obj = new Subclass();
obj.doSomething(); #prints "from Superclass"
}
private void doSomething(){System.out.println("from Superclass");}
}
class Subclass extends Superclass {
private void doSomething(){System.out.println("from Subclass");}
}
I know that subclasses do not inherit the private members of its parent, but here obj manages to call a method to which it should have no access. At compile time obj is of type Superclass, at runtime of type Subclass.
This probably has something to do with the fact that the call to doSomething() is taking place inside the driver class, which happens to be its own class (and why it's possible to invoke doSomething() in the first place).
So the question boils down to, how does obj have access to a private member of its parent?

Private methods are only for the owner.
Not even for the kids, relatives or friends of the owner.

You answered it yourself. As the private methods are not inherited, a superclass reference calls its own private method.

It works because you are casting to a Superclass from within a method of the Superclass. In that context, Superclass.doSomething is available to the compiler.
If you were to change your super and subclasses to two different arbitrary classes A and B, not related to the class containing the main method, and try the same code, the compiler would complain about not having access to the method.

Superclass obj = new Subclass();
At this point, obj is both things, a Subclass, and a Superclass object. The fact that you use Superclass in the declaration of the variable is just a matter of casting it.
When you do: obj.doSomething(), you are telling the compiler to call the private method doSomething() of obj. Because you are doing it from the main static method inside Superclass, the compiler can call it.
If you would use the main method of Subclass rather than the one in Superclass, you would not be able to access that method because, as you said, it's neither inherited nor a part of your definition of Subclass.
So basically you understood inheritance correctly. The problem was related to the visibility of private methods.

When you used this line:
Superclass obj = new Subclass();
You casted Subclass into a Superclass Object, which uses only the methods of the Superclass and the same data. If you casted it back into a Subclass, you could use the Subclass methods again, like so:
((Subclass)obj).doSomething(); #prints "from Subclass"

Since the reference type of the object obj is SuperClass, a call to doSomething() tries to access the private method defined in SuperClass itself (private methods cannot be overridden).
As doSomething() is accessible within SuperClass, the main method can call doSomething() without giving any error/s.
Hope this helps! :-)

why it's possible to invoke doSomething() in the first place?
Why not? obj is an instance both of Subclass and Superclass, and as doSomething() is declared in Superclass and obj is used in it, so you've access to Superclass.doSomething(), you may try to rename your method (to e.g.: doAnotherThing()) and you'll still have access to it.
how does obj have access to a private member of its parent?
There is no parent/child for a private method, and as obj is also a type of Superclass, so it has access to all private methods/fields declared within it, because obj is used in this class. You will lose this access privilege if you're outside of Superclass or of a class that has Superclass as a member (nested class).
So What?
There is no relation/inheritance between SuperClass's private methods and SubClass's private methods, even they have the same name and signature, from Java Language Specification, Java SE 8 Edition:
A private method and all methods declared immediately within a final
class (ยง8.1.1.2) behave as if they are final, since it is impossible
to override them.

To understand this question you can relate private method to member variable of super class and sub class.
So we know member variable is not going to be overridden in sub class.
For example:
Class A{
int i = 10;
}
Class B extends A{
int i = 11;
}
Class C extends A {
int i = 12;
}
A a1 = new B();
print(a1.i) // Will print 10
A a2 = new B();
print(a2.i) // Will print 10
Similar way when there is no inheritance reference variable super class is going to be considered.

When we define a private method with the same name in the derived class, it becomes a new method as derived class don't inherit the private members.
Since the private method is not even visible outside the class, we can never call a base class private method from a derived class, it will throw a compilation error:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The method aPrivateMethod() from the type Base is not visible
We can use down casting to the parent class reference to call the derived class private method, which can only be accessed in that derived class.

Related

What's the correct way to override fillInStackTrace()? [duplicate]

I'm dealing with a class which extends JFrame.
It's not my code and it makes a call to super before it begins constructing the GUI. I'm wondering why this is done since I've always just accessed the methods of the superclass without having to call super();
There is an implicit call to super() with no arguments for all classes that have a parent - which is every user defined class in Java - so calling it explicitly is usually not required. However, you may use the call to super() with arguments if the parent's constructor takes parameters, and you wish to specify them. Moreover, if the parent's constructor takes parameters, and it has no default parameter-less constructor, you will need to call super() with argument(s).
An example, where the explicit call to super() gives you some extra control over the title of the frame:
class MyFrame extends JFrame
{
public MyFrame() {
super("My Window Title");
...
}
}
A call to your parent class's empty constructor super() is done automatically when you don't do it yourself. That's the reason you've never had to do it in your code. It was done for you.
When your superclass doesn't have a no-arg constructor, the compiler will require you to call super with the appropriate arguments. The compiler will make sure that you instantiate the class correctly. So this is not something you have to worry about too much.
Whether you call super() in your constructor or not, it doesn't affect your ability to call the methods of your parent class.
As a side note, some say that it's generally best to make that call manually for reasons of clarity.
None of the above answers answer the 'why'.
Found a good explanation here:
A subclass can have its own private data members, so a subclass can
also have its own constructors.
The constructors of the subclass can initialize only the instance
variables of the subclass. Thus, when a subclass object is
instantiated the subclass object must also automatically execute one
of the constructors of the superclass.
You might also want to read everything about the super keyword here or watch everything about the super keyword here.
We can access super class elements by using super keyword
Consider we have two classes, Parent class and Child class, with different implementations of method foo. Now in child class if we want to call the method foo of parent class, we can do so by super.foo(); we can also access parent elements by super keyword.
class parent {
String str="I am parent";
//method of parent Class
public void foo() {
System.out.println("Hello World " + str);
}
}
class child extends parent {
String str="I am child";
// different foo implementation in child Class
public void foo() {
System.out.println("Hello World "+str);
}
// calling the foo method of parent class
public void parentClassFoo(){
super.foo();
}
// changing the value of str in parent class and calling the foo method of parent class
public void parentClassFooStr(){
super.str="parent string changed";
super.foo();
}
}
public class Main{
public static void main(String args[]) {
child obj = new child();
obj.foo();
obj.parentClassFoo();
obj.parentClassFooStr();
}
}
It simply calls the default constructor of the superclass.
We use super keyword to call the members of the Superclass.
As a subclass inherits all the members (fields, methods, nested classes) from its parent and since Constructors are NOT members (They don't belong to objects. They are responsible for creating objects), they are NOT inherited by subclasses.
So we have to explicitly give the call for parent constructor so that the chain of constructor remains connected if we need to create an object for the superclass. At the time of object creation, only one constructor can be called. Through super, we can call the other constructor from within the current constructor when needed.
If you are thinking why it's there for a class that is not extending any other class, then just remember every class follows object class by default. So it's a good practice to keep super in your constructor.
Note: Even if you don't have super() in your first statement, the compiler will add it for you!
We can Access SuperClass members using super keyword
If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super. You can also use super to refer to a hidden field (although hiding fields is discouraged). Consider this class, Superclass:
public class Superclass {
public void printMethod() {
System.out.println("Printed in Superclass.");
}
}
// Here is a subclass, called Subclass, that overrides printMethod():
public class Subclass extends Superclass {
// overrides printMethod in Superclass
public void printMethod() {
super.printMethod();
System.out.println("Printed in Subclass");
}
public static void main(String[] args) {
Subclass s = new Subclass();
s.printMethod();
}
}
Within Subclass, the simple name printMethod() refers to the one declared in Subclass, which overrides the one in Superclass. So, to refer to printMethod() inherited from Superclass, Subclass must use a qualified name, using super as shown. Compiling and executing Subclass prints the following:
Printed in Superclass.
Printed in Subclass
as constructor is not a part of class,
so while calling it cannot be implemented,
by using SUPER() we can call the members and memberfunctions in constructor.

Java accessing private superclass member through protected getter

I know that in Java you can access a private member of a superclass in the subclass as long as the superclass provides a public or protected getter method. I also know however that the subclass does not actually inherit the private member. Considering the following scenario....
Class A {
private var = 2;
protected int getVar(){
return var;
}
}
Class B extends A{
public void printVar(){
System.out.println(getVar());
}
}
Class Main{
public static void main(args []){
B b= new B();
b.printVar();
}
}
I want to understand, since we are creating an instance of the subclass B, what exactly and when is that private member allocated to memory, and what is it's scope? How does it even exist since an instance of A was actually never created? It's not a static variable, or final so is it stack dynamic or implicitly heap dynamic? I thought that when you instantiate a subclass from a super class you inherit the members that aren't private and methods as well and then those get instantiated as part of an object instance of the sub class (unless they're overridden etc), so there is only one object allocated as a heap dynamic variable. But if these private members are not inherited then does the compiler simply provide a stack dynamic reference to them in case the inherited getter method is invoked and only in that case?
Your assumption that the private members of the super-class are not inherited by the sub-class is wrong. All members are inherited. The private members of the sub-class are part of the sub-class instance, but they can't be accessed directly by the code of the sub-class.
Having a protected getter in the super-class that returns the value of the private member gives the sub-class a means to access the value of the private member (though it can't modify it, unless you also have a protected or public setter in the super-class).
I also know however that the subclass does not actually inherit the private member.
Yes it does. An instance of B is an instance of A, and it contains all the same fields. You don't have direct access to the private fields anymore, but they still exist.
How does it even exist since an instance of A was actually never created?
When you create B, a constructor in A is called as well, which makes sure that the B instance is correctly initialized as a valid A. Don't think of a subclass as something different than it's superclass. A B is still an A; it just does more.

Understanding inheritance and overriding

Actually my question was kind of answered already but I can't understand it properly. here is a code snippet:
public class Superclass {
public static void main (String[] args){
Superclass obj = new Subclass();
obj.doSomething(); #prints "from Superclass"
}
private void doSomething(){System.out.println("from Superclass");}
}
class Subclass extends Superclass {
private void doSomething(){System.out.println("from Subclass");}
}
It prints out : "from Superclass"
Since the reference type of the object obj is SuperClass, a call to
doSomething() tries to access the private method defined in SuperClass
itself (private methods cannot be overridden). As doSomething() is
accessible within SuperClass, the main method can call doSomething()
without giving any error/s.
As far as I can imagine the method calling works this way: (maybe I am totally wrong about this):
The instances of an object store only the data in themselves and when I call an instance method Java takes a look at the type of the reference variable and calls the method from the class of that type.
(It seems logical to me and explains why the code above prints "from Superclass")
But changing the access modifier in the first doSomething() method to protected confuses me, because I can't understand how Java knows there is an overriding if the reference type is the SuperClass and not the SubClass. Does overriding change the method in the Superclass as well?
Or am I totally wrong about how method calling and overriding works?
I would really appreciate If someone could help me out and explain what I am missing.
Private methods along with static methods and all variables cannot be overridden, they can be hidden. So you would need to change the access modifier of your method from private to any other access modifier.
N.B: There are a few protocols to follow when overriding a method; The access modifier of the method defined in the sub-class must have the same level of access if not more accessible than the method that is being overridden. Return types must be covariant etc...
The functionality of overriding a method is simply defining another way to execute the same method using inheritance.
No, overriding doesn't change at all the super class (unless you're doing some weird things with reflection, but that's another story).
The private keyword is used when only the class itself can "see" the method. On the other hand, the protected keyword is used exactly for inheritance: the class and it's childs can see the method. That's why you can only override protected methods.
Since you have defined "doSomething" as private method, your override did not work. Change it to public or protected and then see output.
To understand it better, move Subclass in another java file. Now tell me, can you make a private method call from an object handle?

Why exactly does the no-arg constructor of parent class get invoked while creating an instance of child class? [duplicate]

I have a question about inheritance in Java.
I have two classes A and B , and class B, inherits from A:
public class A {
public A() {
System.out.println("Hi!");
}
}
public class B extends A {
public B() {
System.out.println("Bye!");
}
public static void main(String[] args) {
B b = new B();
}
}
When I run program B, the output is:
Hi!
Bye!
Question : why the constructor of class A is invoked, when I create and object of class B ?
I know that B inherits everything from A - all instance or class variables, and all methods, and in this sense an object of B has all characteristics of A plus some other characteristics defined in B. However, I didn't know and didn't imagine that when I create an object of type B, the constructor of A is also invoked.
So, writing this:
B b = new B();
creates Two objects - one of type B, and one of type A.
This is getting interesting,
can somebody explain why exactly this happens?
It doesn't create two objects, only one: B.
When inheriting from another class, you must call super() in your constructor. If you don't, the compiler will insert that call for you as you can plainly see.
The superclass constructors are called because otherwise the object would be left in an uninitialized state, possibly unbeknownst to the developer of the subclass.
Your subclass actually looks like this after the compiler inserts the super call:
public class B extends A {
public B() {
super();
System.out.println("Bye!");
}
}
It doesn't create 2 objects, it only creates one instance of B. The reason the super class constructor is invoked is because, like you said, B has all of the fields of A, and these fields need to be initialized.
Remember inheritance is an "is a" relationship between the base class and the subclass, thus every time you have an instance of a subclass, by definition you will also have an instance of the base class (as part of the instance, not as two separate instances). To initialize the base class properly the constructor is called.
Additionally, think about what would happen if you subclass depended on some internal state of the base class. Wouldn't you want the instance of the base class to be initialized then?
This is done because the constructor is used to initialize the object. Since B is also an A, it calls the constructor for A first, then the constructor for B.
As a side note, you can use super(arg1, etc) to choose which constructor of A is called based on the parameter types you pass... but it must be the first line in the constructor.
The constructor contains all of the initialization for A. You are not creating two objects. You are creating one object, then running the initializer for the superclass to initialize its members, and then running the initializer for the deriving class to initialize its members.
It does not create two objects, it just creates one object b. b is of type B and of type A. A constructor is basically saying here is what you need to do to construct me. So when you are creating a new "B" instance, you are building an object that is both a B() and an A(). Imagine the following scenario:
class Q {
int i;
public Q() {
// set default value
i= 99;
}
}
class Z extends Q {
public Z() {
}
}
If the constructor for Q WAS NOT called, how would i get its default value?
The creation of B does not create an extra A.
But by creating B, you create a kind of A, because B is a A.
Java/C++ call the constructor of A for your implicitly. Why? Language design. But doing so is fine, because the constructor of A might contain some initializations. And as B uses all the features and bugs of A, these features better be initialized properly.
The constructor of a class is very important concept in most OOP
Classes, by providing state and the means to manipulate that state, allow the easier maintenance of invariants. The constructors role is to get the class into a state that conforms to those invariants (or throws thus forbidding usage of an invliad object).
this is somewhat looser than intended in many languages since the constructor is allowed to pass its own 'this' reference elsewhere but this is at least under the control of the class (as such it can know that it is in a sufficiently stable and valid state for it to be accessible to the rest of the world)
Inheritance makes this complex since B is-a A in a very real sense and thus can invoke any of the methods provided by A. The parts of B that are A should therefore get their chance to initialize themselves before B gets a look in, thus the constructor for A is called before the real work of the B constructor begins.
If A intializes members in it's constructor and you forget to call super in your derived class then the members of A could be in a bad state. Java is trying to stop you from shooting yourself in the foot.
Only one object is created, both contractors are running on the same object.
The reason is simple, as you know B has all the variables and methods of A, so if some variable of A needs initializing so methods of A can work someone has to initialize it - and that someone is A's constructor.
for example:
public class A {
public A() {
x = 1;
}
private int x;
public int getX() {
return x;
}
}
public class B extends A {
public B() {
}
public static void main(String[] args) {
B b = new B();
System.out.println(b.getX()); // should print 1
}
}
When new object is create(B), inside B A object is created(because of extends keywords) . In B class JVM search B class constructor, but due to extends keywords it goes to super class constructor. inside A class x value is initialized. But x is private so that we can access outside class throw getXxx() method and get the result.
When sub class object is created then internally it was not created for super class object.But the memory should be allocated for super class members.
In java when you create an object of child class the constructor of parent class is always called because Object class is the parent of every super class and when you call the constructor of Object class then only your object is created and java does not support multiple inheritance in case of class so if you extends any other class then the relationship between you child class and the Object class is through the Parent class so to call the constructor of the Object class the constructor of Parent class must be called.
Every superclass has a constructor and each constructor up the hierarchy runs at the time an object of a subclass is created.
if super class object is not created then how sub class is accessing super class non static methods and variables.
I studied that non-static methods and variables can be accessed only through objects..

A call to a static method within the parameter list of super() is valid in Java. Why?

Let's look at the following code snippet in Java.
package trickyjava;
class A
{
public A(String s)
{
System.out.println(s);
}
}
final class B extends A
{
public B()
{
super(method()); // Calling the following method first.
}
private static String method()
{
return "method invoked";
}
}
final public class Main
{
public static void main(String[] args)
{
B b = new B();
}
}
By convention, the super() constructor in Java must be the first statement in the relevant constructor body. In the above code, we are calling the static method in the super() constructor parameter list itself super(method());.
It means that in the call to super in the constructor B(), a method is being
called BEFORE the call to super is made! This should be forbidden by the compiler but it works nice. This is somewhat equivalent to the following statements.
String s = method();
super(s);
However, it's illegal causing a compile-time error indicating that "call to super must be first statement in constructor". Why? and why it's equivalent super(method()); is valid and the compiler doesn't complain any more?
The key thing here is the static modifier. Static methods are tied to the class, instance methods (normal methods) are tied to an object (class instance). The constructor initializes an object from a class, therefore the class must already have been fully loaded. It is therefore no problem to call a static method as part of the constructor.
The sequence of events to load a class and create an object is like this:
load class
initialize static variables
create object
initialize object <-- with constructor
object is now ready for use
(simplified*)
By the time the object constructor is called, the static methods and variables are available.
Think of the class and its static members as a blueprint for the objects of that class. You can only create the objects when the blueprint is already there.
The constructor is also called the initializer. If you throw an exception from a constructor and print the stack trace, you'll notice it's called <init> in the stack frame. Instance methods can only be called after an object has been constructed. It is not possible to use an instance method as the parameter for the super(...) call in your constructor.
If you create multiple objects of the same class, steps 1 and 2 happen only once.
(*static initializers and instance initializers left out for clarity)
Yep, checking the JVM spec (though admittedly an old one):
In the instance init method, no reference to "this" (including the implicit reference of a return) may occur before a call to either another init method in the same class or an init method in the superclass has occurred.
This is really the only real restriction, so far as I can see.
The aim of requiring the super constructor to be invoked first is to ensure that the "super object" is fully initialized before it is used (It falls short of actually enforcing this because the super constructor can leak this, but that's another matter).
Calling a non-static method on this would allow the method to see uninitialized fields and is therefore forbidden. A static method can only see these fields if it is passed this as argument. Since accessing this and super is illegal in super constructor invocation expressions, and the call to super happens before the declaration of any variables that might point to this, allowing calls to static methods in super constructor invocation expressions is safe.
It is also useful, because it allows to compute the arguments to the super constructor in an arbitrarily complex manner. If calls to static methods weren't allowed, it would be impossible to use control flow statements in such a computation. Something as simple as:
class Sub extends Super {
Sub(Integer... ints) {
super(Arrays.asList(ints));
}
}
would be impossible.
This is one situation where the java syntax hides what's really going on, and C# makes it a bit clearer.
In C# your B would look like
class B : A {
public B() : base(method()) {
}
private static String method() {
return "method invoker";
}
}
Although the java syntax places super(method) within the constructor it's not really called there: All the parent initialization is run before your subclass constructor. The C# code shows this a little more clearly; by placing super(method()) at the first line of the java constructor you're simply telling java to use the parameterized constructor of the super class rather than the parameterless version; this way you can pass variables to the parent constructor and they'll be used in the initialization of the parent level fields before your child's constructor code runs.
The reason that super(method()) is valid (as the first line in a java constructor) is because method() is being loaded with the static elements--before the non-static ones, including the constructors--which allows it to be called not only before B(), but before A(String) as well. By saying
public B() {
String s = method();
super(s);
}
you're telling the java compiler to initialize the super object with the default constructor (because the call to super() isn't the first line) and you're ready to initialize the subclass, but the compiler then becomes confused when it sees that you're trying to initialize with super(String) after super() has already run.
A call to super is a must in java to allow the parent to get initalized before anything with child class starts.
In the case above, if java allows String s= method(); before the call to super, it opens up flood gate of things that can be done before a call to super. that would risk so many things, essentially that allows a half baked class to be used. Which is rightly not allowed. It would allow things like object state (some of which may belong to the parent) being modified before it was properly created.
In case of super(method()); call, we still adhere to the policy of completing parent initialization before child. and we can use a static member only, and static member of child classes are available before any child objects are created anyways. so the method is avilable and can be called.
OK..i think, this one could be relevant that, if we are calling some member with Super, then it first try to invoke in super class and if it doesn't find same one then it'll try to invoke the same in subclass.
PS: correct me if i'm wrong

Categories

Resources