Overriding rules in Java - java

Here are two examples:
public class A {
public void foo(A a) {
System.out.println("in A");
}
}
public class B extends A {
public void foo(B b) { // (1)
System.out.println("in B");
}
public void f(Object o) { // (2)
System.out.println("in B");
}
}
I don't understand how come (1) and (2) are considered to be an overrided method for A's foo(). method number 1 accepts a lower class than the original foo(), I mean that I can't send her any class of A. as I see it, (1) does not extend foo(), but it is still counts as an override- why?( Similar argument for (2), but opposite).
The reason that I made me think that it is overrided is this:
when I'm trying to run
B b = new B();
b.foo(b);
It checks if A has a foo that accepts B. since every B is an A, it does have one so it ought to print "in A" and not "in B" because B does not overrides it. but it prints "in B"..

Neither of them override the super class A'a method.
class A {
public void foo(A a) {
System.out.println("in A");
}
}
class B extends A {
#Override
public void foo(B b) {
System.out.println("in B");
}
#Override
public void foo(Object o) {
System.out.println("in B");
}
}
When I compile the above I get errors:
$ javac -g O.java
O.java:10: method does not override or implement a method from a supertype
#Override
^
O.java:14: method does not override or implement a method from a supertype
#Override
^
2 errors
But note that it is ok to return a subclass from an overriding method. The following compiles without error.
class A {
public A foo() {
System.out.println("in A");
return this;
}
}
class B extends A {
#Override
public B foo() {
System.out.println("in B");
return this;
}
}

For overriding to work, method signatures should be the same. In this case, they aren't because they differ in the arguments they take. They are just member functions with 1,2 being overloads. ( Considering 2 as a typo. It should be foo instead of f )

Neither 1) nor 2) override anything, as you can verify that by adding the #Override annotation:
public class B extends A {
#Override
public void foo(B b) {
System.out.println("in B");
}
#Override
public void f(Object o) {
System.out.println("in B");
}
}
Neither method will compile, since it doesn't override anything.

Related

Making abstract an overridden method

Here's something I quite understand:
abstract class A {
public void foo() {
System.out.println("a");
}
}
abstract class B extends A {
#Override
public abstract void foo();
public void bar() {
super.foo();
foo();
}
}
class C extends B {
#Override
public void foo() {
System.out.println("c");
}
}
public static void main(String[] args) {
new C().foo();
new C().bar();
}
new C().foo() prints c to the console, while new C().bar() prints a then c.
Calling super.foo() is illegal in the #foo() implementation of the C class.
I don't have a clear question, but if anyone could give a complete explanation of what is going on with the foo method, it may be interesting I think.
A is super class for B, so calling super.foo() inside B calls method defined in A, and calling foo() inside the same class will invoke its own implementation that should be delivered by any subclass.
You cannot use super.foo() within C class because it is defined as abstract in B and cannot be invoked directly.

Why is "this" from superclass calling method from subclass?

I'm running over this problem while working with the following inheritance and JDK 14
interface A {
default void a() {
System.out.println("default a");
}
default void b() {
System.out.println("default b");
}
}
class AImp implements A {
#Override
public void a() {
System.out.println("a from AImp");
}
#Override
public void b() {
System.out.println("b from AImp");
this.a();
}
}
class B extends AImp {
#Override
public void a() {
System.out.println("a from B");
}
#Override
public void b() {
System.out.println("b from B");
super.b();
}
}
when I run
B b = new B();
b.b();
console gives
b from B
b from AImp
a from B
How come the keyword this in the AImp is referencing the instance of class B?
Am I being confused with something here?
Thank you for spending time.
You have created an instance of B, it is it's dynamic type and due to dynamic binding always the method declared in B is called, because it overrides from A.
It does not matter from where you call the method, but it matters, what is the dynamic type.
With super.method() it is different, it explicitly goes up in the inheritance.
Note: constructors are not overriden, ever. So calling this(params) will not delegate to subclass.

About Method Overloading in Java

Can method overloading take place only within the same class? Or can it take place within sub classes?
There is no restriction on overloading within sub-classes. For example, I could have:
public class A {
public String test(String input) {
//do something
}
}
public class B extends A {
public String test(String input, String input2) {
//do something
}
}
B testInstance = new B();
testInstance.test("one", "two");
testInstance.test("one");
For questions like this, you can always try it yourself and find out.
In a word - yes. You can overload methods in a subclass. E.g.:
public class Parent {
public void print(String s) {
System.out.println("That was a string: " + s);
}
}
public class Child extends Parent{
public void print(int i) {
System.out.println("That was an int: " + i);
}
}
public class Main {
public static void main(String[] args) {
Child c = new Child();
c.print("hello"); // prints "That was a string: hello"
c.print(7); // prints "That was an int: 7"
}
}
When you overload a method, it's basically creating an entirely new method with no direct association with the other of the same name, it's the signature that matters.
so if you make a method in the subclass that has different signature it will be treated as different and new method for that class by the compiler so it won't be relating it to the method of super class.
Overloading can be possible in sub classes. If you create a method with the same name as in super class with different parameter then it will be treated as separate method. Sub class will have methods from super class as well so which method to be called is decided at compile time based on the parameter type. Which method to be called is declared at compile time that is why it's called static polymorphism. Here is the example -
Class A{
void m1(int x){
System.out.println("m1 in A");
}
}
Class B extends A
{
void m1(String str)
{
System.out.println("m1 in B");
}
}
Public Class Test
{
public static void main(String[] aa)
{
B b = new B();
b.m1(10);
b.m1("Hello World!!")
}
}
Hope this will help.

Java: recursion within main-class calls subclass-method instead of its own method

Example:
class MainClass {
public doIt() {
...
else doIt();
}
}
class SubClass extends MainClass {
#Override
public doIt() {
super.doIt();
...
}
}
Now the problem is:
I call SubClass.doIt()
MainClass.doIt() is called
MainClass.doIt() makes recursion calling doIt()
But: the SubClass.doIt() is called instead of MainClass.doIt()
That is very strange behaviour and problems are programmed! I tried to call the recursion with this.doIt() but that didn't help.
Someone has an idea?
Thanks alot for your answers, this problem is solved.
That's the supposed behavior, by not setting a method final, that means it can be overriden, so you must always take into account someone can do this. Call's to that method are never guaranteed to be to the method at that level.
You can however solve this problem elegantly, by using a (protected) final method:
class MainClass {
protected final void innerDoIt () { //final: so no #Override
...
else innerDoIt();
}
public void doIt() {
innerDoIt();
}
}
And then:
class SubClass extends MainClass {
#Override
public doIt() {
super.doIt();
...
}
}
final ensures, the method can't be overriden. So at that moment, you have a contract (guarantee) that the innerDoIt method is indeed the innerDoIt method you think it is.
So in case you don't wan't the caller to get overriden, simply hedge it into another final method. By making it protected, that method can also be called by the SubClass.
public class Main {
public static void main(String[] args) {
B b = new B();
b.doIt();
System.out.println();
A a = new B();
a.doIt();
}
public static class A{
boolean check=false;
public void doIt(){
System.out.println("A start");
if(check){
}
else{
check = true;
doIt();
}
System.out.println("A end");
}
}
public static class B extends A{
#Override
public void doIt() {
System.out.println("B start");
super.doIt();
System.out.println("B end");
}
}
}
In this example, both b and a are instances of class B, so as you probably expect, a.doIt() and b.doIt() will output the same result.
B start
A start
B start
A start
A end
B end
A end
B end
B start
A start
B start
A start
A end
B end
A end
B end
When you call doIt(), you are implicitly calling this.doIt(), and this is an instance of class B. There is no syntax to do what you want do without seperating the content of doIt() (see CommuSoft's answer)

Replace empty method with method from a class where it is used

In the following scenario, I want to replace Class B's (similarly D, E, F, etc.) method doSomething() with the method in Class A where it will be used. How would I go about this? Made up some example, hope it gets the message across
public class B implements GetNames{
public void getNameA(){ return "NameA"; }
public void getNameB() { return "NameB"; }
public void doStuff(){
//print names
doSomething(getNameA(), getNameB());
//print names
}
public void doSomething(String a, String b){}
}
public class A{
public void someMethod(){
B b = new B();
b.doStuff(); //*So I want it to call the method in B but somehow replace the doSomething method in B with the doSomething method in A
}
public void doSomething(String a, String b){
//print 'blabla' + a
//print 'blablabla' + b
//concatenate and print
}
}
Made abstract class A implement interface GetNames and then extend it in class B:
public abstract class A implements GetNames {
public void doSomething(String a, String b){
//print 'blabla' + a
//print 'blablabla' + b
//concatenate and print
}
}
public class B extends A {
public void getNameA(){ return "NameA"; }
public void getNameB() { return "NameB"; }
public void doStuff(){
// class A's doSomething will be called
doSomething(getNameA(), getNameB());
//print names
}
}
Class A should extend class B. If you make B an abstract class, the B.java file would look something like this:
public abstract class B {
...
public abstract void doSomething(String a, String b);
...
}
An abstract class has some functionality, like the getNameA method, which is already defined, but other methods like doSomething are left to its subclasses to implement.
Change class A to read:
public class A extends B {
...
#Override
public void doSomething(String a, String b) {
// custom behaviour
}
}
If what you want is to just make an instance of class B that has a different implementation of the method doSomething then what you could do is this:
B myBInstance = new B() {
#Override
public void doSomething(String a, String b) {
// custom behaviour here
}
};
myBInstance.doStuff();
Style-wise and design-wise though, this is only a quick-and-dirty way to define behaviour for a one-time use of B.

Categories