When it comes to over - riding , there is only one rule related to access specifiers
"The subclass overridden method cannot have weaker access than super class method"
why is the child class restricted to have stronger access specifier ?
what draw back may it invite , I am guessing something to occur on design level.
let us consider the rule didn't exist , in that case
1 : parent class having weaker access say public
2 : child class having stronger access say private
so if any external class tries to access the method , it still can access from child class as it will be inherited in child class and will be available to use with object reference
please clarify.
public class A
{
public void methOne(int a)
{
// something
}
}
class B extends A
{
private void methOne(int a)
{
// something else
}
}
class C
{
public static void main(String args[])
{
new B().methOne();
// in this special case after removing the specifier rule it will execute the method from parent class.
}
}
What you have tried to do is invalid, because by extending A all instances of B must be able to act as though they were an A. For example:
A a = new A();
a.methOne(1);
Compared to:
A a = new B();
a.methOne(1);
In both cases all the code knows is that it has an A and that all As have a method called methOne. In the second case that is broken as you have tried to make the method private but A has already said that it has a method by that name available.
It works the other way around because you don't invalidate the contract. If the method was private in A and public in B then you can still use an instance of B as though it was an A, you just don't have access to that method unless you know you are working with a B.
When you re declare the method of your parent class in you child class it is method overriding which in simple terms would mean you would want the objects of your child class to call its method instead of the parents method with same name and signature. Now in child class if you have a more restrictive access specifier say by making private as in your case you are effectively telling the JVM not to call the method though it is visible to the child objects which would lead to confusion as if you have exposed only your parent class to outside world then in some of your classes if you could make this method private then JVM shouldnot allow these methods to be called if such child objects are passed .
Q. so if any external class tries to access the method , it still can access from child class as it will be inherited in child class and will be available to use with object reference
This in your above case defeats the purpose of encapsulation by making the method private. By declaring a method private you are actually trying to tell that make my parent class corresponding method not visible to outside world which is not posssible as your parent method is visible to your child class.
Related
Suppose I have these classes:
public class ChildClass extends ParentClass
{
// some class definition here
}
public abstract class ParentClass
{
public static void printClass()
{
// get the class that extends this one (and for example, print it)
}
// some class definition here
}
Lets say when calling ParentClass.printClass() I want to print the name of the class (like doing System.out.println(ParentClass.class)). When then extending ParentClass (for example like in ChildClass) and calling ChildClass.printClass(), I want it to print the name of the extending class (like doing System.out.println(ChildClass.class)). Is this somehow possible?
I've found a way to get the class from inside a static method by using MethodHandles.lookup().lookupClass(), but when using it inside of ParentClass.printClass and extending ParentClass, then calling printClass on the extending Class, I always get the class of ParentClass.
static methods are best thought of as living entirely outside of the class itself. The reason they do show up in classes is because of the design of java (the language) itself: Types aren't just types with a hierarchy, they also serve as the primary vehicle for java's namespacing system.
Types live in packages, packages are the top level namespace concept for types. So how do you refer to a method? There's only one way: Via the type system. Hence, static methods do have to be placed inside a type. But that's about where it ends.
They do not inherit, at all. When you write:
ChildClass.lookupClass()
The compiler just figures out: Right, well, you are clearly referring to the lookupClass() method in ParentClass so that is what I will compile. You can see this in action yourself by running javap -c -p MyExample. The same principle applies to non-static methods, even.
For instance methods, the runtime undoes this maneuvre: Whenever you invoke a method on any object, the runtime system will always perform dynamic dispatch; you can't opt out of this. You may write:
AbstractList<String> list = new ArrayList<String>();
list.sort(someComparator);
and you can use javap to verify that this will end up writing into the class file that the method AbstractList::sort is invoked. But, at runtime the JVM will always check what list is actually pointing at - it's an instance of ArrayList, not AbstractList (that's obvious: AbstractList is abstract; no object can ever be directly instantiated as `new AbstractList). If ArrayList has its own take on the sort method, then that will be called.
The key takeaway of all that is: Static methods do not inherit, therefore, this dynamic dispatch system is not available to them, therefore, what you want cannot be done in that fashion.
So what to do?
It feels like what you're doing is attempting to associate a hierarchy to properties that apply to the class itself. In other words, that you want there to be a hierarchical relationship between the notion of 'ParentClass's lookupClass method and ChildClass's lookupClass method - lookupClass is not a thing you ask an instance of ChildClass or ParentClass - you ask it at the notion of the these types themselves.
If you think about it for a moment, constructors are the same way. You don't 'ask' an instance of ArrayList for a new arraylist. You ask ArrayList, the concept. Both 'do not really do' inheritance and cannot be abstracted into a type hierarchy.
This is where factory classes come in.
Factory classes as a concept are just 'hierarchicalizing' staticness, by removing static from it: Create a sibling type to your class hierarchy (ParentClassFactory for example):
abstract class ParentClassFactory {
abstract ParentClass create();
abstract void printClass();
}
and then, in tandem with writing ChildClass, you also write ChildClassFactory. Generally factories have just one instance - you may want to employ the singleton pattern for this. Now you can do it just fine:
class ChildClassFactory extends ParentClassFactory {
private static final ChildClassFactory INSTANCE = new ChildClassFactory();
public static ChildClassFactory instance() { return INSTANCE; }
public ParentClass create() { return new ChildClass(); }
public void printClass() { System.out.println(ChildClass.class); }
}
// elsewhere:
// actually gets the ChildClassFactory singleton:
ParentClassFactory factory = ....;
factory.printClass(); // will print ChildClass!
Quoting #RealSkeptic:
Static methods are not inherited. The fact that you can call ChildClass.printClass() is just syntactic sugar. It actually always calls ParentClass.printClass(). So you can't do something like that with a static method, only an inheritable non-static one.
I know that super will be called every time we create a child class object. But, what I specifically want to know is that will it load the class or will it create the object of that parent class.
Thanks in advance.
You have a single object.
As a class is instantiated, it invokes first the constructor of the parent class. And for each parent class, it follows the same logic : it invokes first the constructor of the parent class.
Suppose : A extends B extends C.
new A() results to the B constructor invocation that invokes itself the C constructor.
As C then B constructor invocations are returned, the A constructor can go on and the instance A is created.
But, what I specifically want to know is that will it load the class
or will it create the object of that parent class.
Similarly to the constructor execution, before loading a class, its parent class has to be loaded first and that recursively for each parent class.
Here classes corresponding to A extends B extends C :
class C {
public C(){
System.out.println("C constructor");
}
}
class B extends C{
public B() {
System.out.println("B constructor");
}
}
class A extends B{
public A() {
System.out.println("A constructor");
}
}
public class Test {
public static void main(String[] args) {
new A();
}
}
Compile these classes and then execute the Test class that creates a A instance in its main() method by specifying the -verbose flag (enable by default the classes logs) in the java command :
java -verbose Test
And you should see in the output standard something like :
[Loaded java.lang.Object from C:\...]
[Loaded java.io.Serializable from C:\...]
... // load all classes required until loaded C, B and A classes
[Loaded C from file:/C:/...]
[Loaded B from file:/C:/...]
[Loaded A from file:/C:/...]
C constructor
B constructor
A constructor
It confirms that :
the parent classes need to be loaded first by starting by the root parent class ( Object) until the closest parent class(B).
no constructor is executed before all classes of the hierarchy be loaded
the constructors of the parent classes are always executed before the constructor of the instantiated class by starting by the root parent constructor ( Object) until the closest parent constructor(B).
The constructor is called, therefore an object of the parent class is created. That object is used later to build an object of the child class. The reason for this is that an object of the child class is an object of the parent class with more things.
Because the child class inherits properties and methods from the parent class, the entire class hierarchy (including superclasses and implemented interfaces) are loaded.
When you create an instance of the childclass, only a single object of type childclass is created (instantiated). There are no additional instances of any parent(s).
The properties and methods declared on parent classes are accessible via the childclass instance, and due to this inheritance the childclass instance will be accepted as argument to any methods that expect an instance of the parent (or any interfaces that it or any parent implements).
If you think of the code as a contractual design, this makes perfect sense:
The parent class declaration establishes that certain methods are available to call on itself or any of its children. The same is true for interfaces. For example, all employment contracts in the real world must contain certain clauses, but the rest is up to the company.
By inheriting (extends or implements) it is guaranteed that the child will also automatically provide the same methods. For example, we can assume that any law-abiding company will provide employment contracts including those clauses and (once agreed) the signature of both you and the company.
The entire hierarchy needs to be loaded in order to understand the full contract.For example, if there is a dispute, the lawyers who examine a contract will check what the law prescribes, perhaps by looking at a sample contract provided by the legislating body. The parentClass is that sample in the problem.
We only need one object instance. For example you won't get two employment contracts, one for the basic stuff and another with more information. You will receive and sign a single document.
Finally, in my analog, any employment contract (no matter how it is phrased) will be acceptable to any agency that asks you to prove your relationship to the company that employs you (assuming it is legal and valid by containing the legally prescribed clauses and appropriate signatures).
When you first load a class, all its ancestors are also loaded recursively.
When you instantiate an object you won't instantiate an additional instance of its parent. However, the object you just instantiated is itself also an instance of the parent.
Although, this is a very basic code, it seems there is something fundamentally flawed in Java, or the JVM used by the Eclipse IDE I have used to run the code.
The code runs even though it should not (I think)! The code in A.java simply displays "Hello, I am A!"
Here it is:
import java.lang.*;
import java.util.*;
class A {
private void methodA() {System.out.println("Hello, I am A!");}
public static void main(String[] args) {
A a = new A();
a.methodA(); }
}
I do not understand why, after creating an instance of class A, main() succeeds in running a private method of class A on that instance. Yes, the main method belongs to class A, but it is not accessing the private method from inside the current object in the context of the "this" reference. In fact, since it is a static method, it cannot access non-static members from within the class. Instead of main(), a non-static member method could have invoked methodA() from inside only. But that is another issue since I have not defined any non-static second method.
Now that the inside-view is talked about, let's come back to the point, the outside-view. As you can see, main() attempts to invoke methodA from outside the object and succeeds! Why isn't private getting treated as private?
I am pulling my hair....
Anyone, please reply...
Yes, the main method belongs to class A, but it is not accessing the private method from inside the current object in the context of the "this" reference.
That doesn't matter. That's just not the model of accessibility that Java uses. What's important is the class in which the code is written, not whether it's accessing members in the same object.
This is very useful, as otherwise (for example) it would be impossible to implement an equals method using private members of both classes.
This may not be how you would have chosen to specify the language, but it is how Java is specified. See JLS 6.6.1 for details of accessibility. In particular:
Otherwise, if the member or constructor is declared private, then 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.
Note that protected access is slightly odd here - a protected instance member of class SuperClass can only be accessed within code in SubClass via an expression of either SubClass or a further subclass. But it still doesn't have to be "the same" object.
private modifer
Methods, Variables and Constructors that are declared private can only be accessed within the declared class itself.
private means "private to the class". Not "private to the instance".
That's what allows implementing things like static factory methods calling private constructors, or equals() or compareTo() methods comparing private fields of objects of the same class, or copy constructors, etc.
Private members of enclosing classes are also accessible from inner classes of this enclosing class, and vice-versa.
After the technically correct answers here's my two cents why I think it is quite reasonable to implement private that way:
As I see it the main reason that private methods and attributes exists is "implementation hiding". You are declaring "Don't use this method from outside my class(!), since it might change or disapear anytime I like". So it makes sense to disallow access from outside the class. But if I'm accessing it from another object of the same class I and make any implementation changes I'm well aware of the changes and the accesses of the private members and can act accordingly.
Another thing to think about:
If class B extends class A, then any B-object also is an A-object, but it can't access the private A-methods. Why would that be if private methods were private to the object?
This question already has answers here:
What is the difference between public, protected, package-private and private in Java?
(30 answers)
Closed 8 years ago.
According to my understanding, a protected method can be accessed by any class within the same package, but only subclasses to this class can access from other packages .
package Parent;
public class Parent {
protected void display() {
//Code here
}
}
import Parent;
package Child;
class Child extends Parent{
void view(Parent p1) {
this.display(); // Success
p1.display(); // Error
}
void next(Parent p2) {
p2.foo(); //Success
}
}
Here this.display() is successful because the child class is responsible for implementation. But p1.display() does not work as p1 is not part of Child class.
How can we justify this behaviour in the case of accessing protected methods from classes within the same package?
Your
p1.display();
has the potential of running a method implemented in any package, depending on which exactly Parent subclass you received. This would be in clear violation of the intent behind protected, which is specifically to allow classes designed for extension to provide encapsulated methods to their children.
If that call was allowed, it would be trivially easy for a rogue class to access encapsulated methods from a class completely foreign to it.
The example you have provided is calling the method using an instance of Parent passed to the child. The spec states that access to the field or instance method must be from the subclass when the scope is protected. Notice the portion of the spec that states, access is permitted if and only if the type of the expression Q is S or a subclass of S. In your example the ExpressionName is p1, which is an instance of Parent, making its type not Child or a subclass of Child therefore access is disallowed.
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.
I think I see the point your attempting to make, since Child is a subclass of Parent, when we pass an instance of Parent into a method on Child we should be able to call its protected methods. The rules of the specification prohibit this.
Specification
If you use super.display() it will work. The reason is that protected methods in parent are always visible to child classes whether they are in same package or not. When you just say p1.display() it expects the method to be public as both classes are in different package.
Please read the following to get more understanding on this.
In Java, difference between default, public, protected, and private
So I have a parent class, here refered to as A, and class B which extends A.
public class A
{
private int a = 1;
public int getA()
{
return a;
}
}
public class B extends A
{
private int a = 2;
}
However, when B.getA() is called, it returns 1 from class A instead of the 2 in class B. Did I do something wrong? Because I had a similar problem a couple of months ago, and it miraculously worked after a lot of messing around. The only difference is that the method deals with adding an object to an ArrayList.
Thanks.
Private variables are private even to subclasses. A.a and B.a are two completely different fields. If you want to change data in a subclass, make it a protected field or (better yet) add an optionally abstract getter to the parent class and override it in the subclass.
The reason is that the fields defined in a class are never overriden in subclasses, irrespective of the fields' access modifiers.
If you declare a field in a subclass with the same name as a field in the superclass, your subclass actually has two fields with that name. The field inheritted from the superclass is hidden in the subclass, but (if the access rules permit it) the superclass version can be accessed in the subclass; e.g. by qualifying the field name with the class name.
(In your particular example, the access rules forbid B to access the a declared in A. A private field or method can only be accessed from the class itself or nested classes. But even so, there are two fields called a in any B instance instance.)