Given the following class hierarchy
package pack1;
public class A
{
private int methodOne(int i)
{
return ++i;
}
public int methodTwo(int i)
{
return methodOne(++i);
}
}
package pack2;
import pack1.A;
class B extends A
{
int methodOne(int i)
{
return methodTwo(++i);
}
}
public class MainClass
{
public static void main(String[] args)
{
System.out.println(new B().methodOne(101));
}
}
The output of the above program is 104. Class Bcreates its own version of methodOn() because methodOne() is private in Class A. However, during runtime, when inside methodTwo(), the runtime object is of type Class B. Why would java use the methodOne() in class A as oppose of class B.
This is because, despite the name, the two methods are entirely different. methodOne in class B does not override the method with the same name in class A. As you said, B can't see the private methodOne, so it can't possibly override it. So Java creates two separate methods that are not related in any way. Then A's methodTwo calls the methodOne that's defined in A. If it were public or protected, then other classes might have overridden it, resulting in the late binding we know all too well from Java. However, the methodOne that it sees has never been overridden because B didn't know to do so.
tl;dr: Internally, they're two different and unrelated methods, even though the names are the same.
At very first your code starts executing the code
public static void main(String[] args)
{
System.out.println(new B().methodOne(101)); // it invokes methodOne() of class B.
}
Above code calls methodOne() of class B. Now, MethodOne() is private so it won't override in Class B
Now definition of methodOne() in Class B
int methodOne(int i)
{
return methodTwo(++i); // calling methodTwo() from class A which is a super class of class B.
}
this code is increase the value of i by 1. So, Now i = 102. Now again the methodTwo calling the methodOne() of class B in below code.
public int methodTwo(int i) //methodTwo in class A. part of object due to public access modifier.
{
return methodOne(++i); // it increase the value of i by 1. Now i =103.
}
Now the value of i = 103. Now it calls methodOne() of class A , because methodOne() is private in Class A
private int methodOne(int i)
{
return ++i; //again this increase the value of i by 1. Now i =104.
}
increased the value of i by 1. So, variable i = 104. So, Final value of i is 104 Now.
So, The Final Output is 104.
Related
I have two java class files
Hi.java which belongs to second package
package second;
public class Hi {
protected int v=20;
protected void m(){
System.out.println("i am protectTED");
}
}
S.java which belong to first package
package first;
import second.Hi;
interface i1
{
void m();
int a=200;
}
interface i2{
void m1();
int b=100;
}
class S extends Hi implements i1,i2
{
int a=50;
public void m()
{
System.out.println("hi");
}
public void m1()
{
System.out.println("hello");
}
public static void main(String[] args) {
S s=new S();
/*need correction here (i don't know the exact syntax to mention to get
the desired output)
s.m(); //should invoke method m() from class Hi only.
s.m(); //Should invoke method m() from class S only.
*/
//the following statements prints the desired values
s.m1();
System.out.println(s.v);
System.out.println(i1.a);
System.out.println(s.a);
System.out.println(b);
}
}
when i run the S.java class file method m() in class Hi should be invoked.("my intention") instead method m() of the same class i.e., class S is being invoked.
How to differentiate the 2 methods for invoking. Is it even possible?
when i run the S.java class file method m() in class Hi should be invoked.("my intention") instead method m() of the same class i.e., class S is being invoked.
Correct, because you've overridden it with m in S. Overriding methods is fundamentally different from overriding fields. (And in general, it's best to avoid overriding any fields that are visible to your subclass, as you're doing with a.)
In instance code in S, you can run the inherited m via super: super.m(). But you cannot do that from static code, not even static code in S. You could give yourself a private callSuperM in S:
private void callSuperM() {
super.m();
}
...and then use that in main:
s.callSuperM(); // "i am protectTED"
s.m(); // "hi"
I have one class and one interface:
public interface A {
public void getNum();
}
public class B {
public void getNum() {
System.out.println("4");
}
}
public class C extends B implements A {
protected void getNum() {
System.out.println("3");
}
}
Now my question is, why this code is giving compilation error and how can we avoid it. Is there any way in which we can override this method in class C?
From Java Language Specification:
jls-8.4.8.3
The access modifier (ยง6.6) of an overriding or hiding method must provide at least as much access as the overridden or hidden method, as follows:
If the overridden or hidden method is public, then the overriding or hiding method must be public; otherwise, a compile-time error occurs.
...
Notice that you are trying to override public method getNum() inherited from class B (and also from interface A) with new one that has protected access modifier. It means that you are trying to reduce visibility of this method which according to specification is incorrect.
To be able to override this method you need to use public access modifier with your new version of that method.
Why you cant reduce visibility? Take a look at below code which uses your classes but is placed inside some other package and ask yourself "how should this code behave?".
package my.pckage;
import your.pckage.A;
import your.pckage.C;
public class Test{
public static void main (String[] args){
C C = new C();
c.getNum();// ERROR: Test class doesn't have access to `c`s protected method.
// Why should it have, Test doesn't extend C.
A a = (A)c;// Lets try using other reference
a.getNum();// Should `a` have access to method that is protected in `C`?
// If yes, then what is the point of declaring this method
// protected if all I would have to do to get access to it is
// casting instance of C to A interface?
}
}
Fix the typos and try again ;)
public interface A {
public void getNum();
}
public class B {
protected void getNum() {
System.out.println("4");
}
}
public class C extends B implements A {
public void getNum() {
System.out.println("3");
}
}
First of all scope should be from lower to higher while you are overriding method in Java. scope of subclass method should be high then super class for e.g
Valid Overriding
class B {
protected void getNum() {
System.out.println("4");
}
class C extends B {
public void getNum() {
System.out.println("3");
}
InValid Overriding
class B {
public void getNum() {
System.out.println("4");
}
class C extends B {
protected void getNum() {
System.out.println("3");
}
Your second problem is you have created two public class which is not valid you can create only one public class in your java file.
When you implement an interface you need to compulsorily override it to provide concrete implementation of function(unless the class implementing the interface is abstract). In your case you are implementing an interface which make you implement getNum() function and due to overriding class you have another function with same signature which is not allowed. So you get compilation error.
Possible solution : You can make B as an interface.
The explanation by Pshemo is perfectly right that you can not reduce visibility of overridden or the interface functions.
Lets take an exapmle
class B
{
protected void getProtected1()
{
System.out.println("4");
}
protected void getProtected2()
{
System.out.println("4");
}
public void getPublic1()
{
System.out.println("4");
}
public void getPublic2()
{
System.out.println("4");
}
}
class C extends B
{
#Override
private void getPublic1() //COMPILATION ERROR : Cannot reduce the visibility of the inherited method from myzeromqApp.B
{
System.out.println("3");
}
#Override
protected void getPublic2() //COMPILATION ERROR :Cannot reduce the visibility of the inherited method from myzeromqApp.B
{
System.out.println("3");
}
#Override
private void getProtected1() //COMPILATION ERROR : Cannot reduce the visibility of the inherited method from myzeromqApp.B
{
System.out.println("3");
}
#Override
public void getProtected2() // NO ERROR IT MEANS YOU ARE ALLOWED TO INCREASE THE VISIBILITY
{
System.out.println("3");
}
}
From the above example it is clear that you are not allowed to decrease the visibility of function in any case.
In your question you are trying to implement the interface function and we know interface in Java has rules that,
Method: only public & abstract are permitted
Field: (Variables) only public, static & final are permitted
As thumb of rule, you can never decrease the visibility, of overridden or implemented methods or variables and for interface it is always public (if visibility is concerned) so those should always be public in implemented classes.
As stated, only one public class can be used per file. So, to have them all public, one must create three separate .java files. I will write the code up below, as well as detailing how to override the method to use the correct version of it in each case.
One may always have methods with the same name, but for overriding, they must have different argument lists. This is one of the compiler errors, you have three methods with the same argument lists, namely none. You may create and call the method with the correct argument list to achieve the desired result.
A.java:
package stackOverflow.tests; // Sample package for visibility
public Interface A {
public void getNum(int a); // Method takes a single integer argument
}
B.java:
package stackOverflow.tests;
public class B {
protected void getNum(int a, int b) { // Method takes two integer arguments, differing in the argument list but equal in name
System.out.println("4");
}
}
C.java:
package stackOverflow.tests;
import stackOverflow.tests.A; // Importing both classes to use their methods
import stackOverflow.tests.B;
public class C extends B implements A {
public void getNum(int a, String x) { // Takes an integer and a string argument
System.out.println("3");
}
public void getNum(int a) {
//Do nothing, as in A.java, this code is necessary to be able to override the method.
}
public static void main(String[] arguments) { // Sample main method for implementation
C c = new C(); // Instantiating class C
int test = 0; // Initializing two integer variables and one String variable
int test2 = 0;
String test3 = "";
c.getNum(test); // takes one integer, using getNum() from A.java
c.getNum(test, test2); // takes two integers, using getNum() from B.java
c.getNum(test, test3); // takes an integer and a String, using getNum() from C.java
}
}
Output:
4
3
As seen in the code above, the argument lists define which version of the method is used. As a side tip, the definition getNum(int a) is no different from getNum(int b), so this would result in it not compiling.
In order to get this working you can do something like this since there can be only one public class per file and the file name should be the same name as that of the class
public class HelloWorld{
public static void main(String []args){
C obj=new C();
obj.getNum();
}
}
//interface
interface A {
public void getNum();
}
class B {
protected void getNum() {
System.out.println("4");
}
}
class C extends B implements A {
public void getNum() {
System.out.println("3");
}
}
output:
3
A java class file can have only one public class or interface.
Change the visibility of the interface and the defined class to default level or declare it in separate files.
Only public and abstract modifiers can be applied to interface methods. The class implementing the interface cannot change the visibility of the method (we cannot change it from public to protected).
Lets say I have a class
public class Base {}
and a child class
public class Derived extends Base {
public void Foo(Object i){
System.out.println("derived - object");
}
}
and main class
public class Main {
public static void main(String[] args) {
Derived d = new Derived();
int i = 5;
d.Foo(i);
}
}
In console we will see
derived - object
Some time later I want to modify my superclass like this :
public class Base {
public void Foo(int i) {
System.out.println("base - int");
}
}
Now if I run my programm I will see:
base - int
So can I make a method in superclass not avaliable in my child class?
In result I want to see derived - object.
I see some don't understand what I want so I'll try to explain:
I want to modify only superclass and I don't want to modify my child class.. for example if I will make jar with my superclass and jar with my childs. I don't want to change all jars.. I want to add method into superclass and make it avaliable for superclass..
And such code
public class Main {
public static void main(String[] args) {
Derived d = new Derived();
int i = 5;
d.Foo(i);
Base b = new Base();
b.Foo(i);
}
}
give me
derived - object
base - int
You should use following signature for Foo method in base class:
public void Foo(Object i) {
System.out.println("base - int");
}
This way you can override method Foo from base class. Now you do not override this method but overload it instead.
If you want to use public void Foo(int i) signature in your base class then you can define Foo method in base class as private.
PS: I hope that I've understood you.
private members are limited to the class scope.
default (no keyword for this one) are limited to other members of the same package.
protected are limited to hierarchy.
public are not limited.
So if you don't want your child class to access a member of the superclass (member means methods, enum, variables ...) you should declare your foo like this :
public class Base {
private void Foo(int i) {
System.out.println("base - int");
}
}
Edit from my comment :
if you dont want child class to access a parent's member at compile time I can't see any way to still allow external classes to access it.
You want to block access from close scope while allowing broader scope. This can only be done by overriding the method and throwing an exception for accessviolation or something which is not at compile time but at runtime. Although you could make it work with a custom annotations but I don't know how to do this.
You can make a method final, which means, that the child class cannot override it.
If you do not do that and the child class overrides the method, you cannot call the super classes method from your main.
A Convention note: Please use lowercase method names in java.
package com.abc;
public class TestParentChild {
public static void main(String[] asd) {
Base b = new ChildB();
b.foo(5);
}
}
class Base {
public void foo(int i) {
System.out.println("derived - int");
}
}
class ChildB extends Base {
public void foo(int i) {
System.out.println("derived - object");
}
}
This might help you
i'm relativly new to java and experimantating a bit with javafx
i want to change a variable from class A while using a method from class B
Main: thats the main class, it contains all the needed stuff(shows the primaryStage etc) it does have an constructor, so its not creating an actual "main-object"
public class Main extends Application {
Sub sub = new Sub();
int a;
// stuff
public void aMethod() {
sub.subMethod();
}
}
Sub: this class solely surpose is to change the variable a, it does not contain a constructor to create a "sub-object"
public class Sub {
//stuff
subMethod(){
int a = 5;
}
if i put the line Main main; in the Sub class, the program will give me a nullpointer exception, if i'm calling the subMethod().
ok...i guess cause i didnt actually create the main object... so far so good.
BUT... if i put in the line Main main = new Main(); the program wont even start giving me an "exception while running application" error
the strange thing though is, if i put the line Main main = new Main(); in the subMethod...
subMethod(){
Main main = new Main();
int a = 5;
}
...the damn thing actually works...(well its slow, guess because with every calling of the method its creating a new object)
why is that so?
and how is it done correctly? :)
(using methods of other classes to "overwrite" variables)
regards
Red
You should not create more than one instance of Main in your program. Probably Main is not the best place to store mutable state (class members), but if you want that, you need to pass the instance of Main to subMethod (and make a public, or provide a public setter method):
public class Main extends Application {
Sub sub = new Sub();
public int a;
// stuff
public void aMethod() {
sub.subMethod(this);
}
}
public class Sub {
//stuff
subMethod(Main main){
main.a = 5;
}
So you want a method to change the value of another class's fields. There are a few ways to do this. If you have this class
public Class A {
private int a;
...
public void setA(int a) {
this.a = a;
}
}
You can do something like this
public Class B {
private static A instance;
....
public static void setA(int a) {
instance.setA(a);
}
}
Or you can take the A in as a parameter to the set method
public Class B {
...
public static void setA(A a, int val) {
a.setA(val);
}
}
If you want direct access to the fields on A you have to make them public (this is usually not what you want to do as it gives complete access rather than just giving just the access the other classes require)
Public Class A {
public int a;
...
}
Then you can do
Public Class B {
...
public static void setVal(A a, int val) {
a.a = val;
}
}
Also if you don't have the method setA in B as static you'll have to call it on an instance of B like
B b = new B();
b.setA(a, val);
Where as if it's static you call it on the class B
B.setA(a, val);
public class XXX {
#Test
public void test() {
B b = new B();
b.doY();
}
}
class A {
public void doY() {
XProcedure.doX(this);
}
}
class B extends A {
public void doY() {
super.doY();
XProcedure.doX(this);
}
}
class XProcedure {
public static void doX(A a) {
System.out.println("AAAA!");
}
public static void doX(B b) {
System.out.println("BBBB!");
}
}
The output is
AAAA!
BBBB!
And I wonder why?
Although XProcedure has two methods with the same name - doX, the two signatures are different. The first method gets an instance of class A as a parameter, and the second one gets an instance of class B.
When you call XProcedure.doX(this), the correct method is called according to the class of the passed parameter.
"AAAA!" is printed because of the super.doY() call.
"BBBB!" is printed because of the XProcedure.doX(this); call.
this differs in A's constructor from this in B's constructor for the reasons in Che's answer. Although A's contructor is called from within a B's constructor, in A's scope, the instance is of class A.
You called super.doY which is a method on B's superclass A.
All animals can talk.
A cat is an animal.
A cat talks and drinks milk.