Story of Kungfu Java Valley - Explanation

Story of Kungfu Java Valley - Explanation

In the last article, The story of Kungfu Java Valley , we read about Java Valley and how Po became Master Po. There were many Java concepts we already read in that article. In this article, we’ll focus more on the technical side and reveal remaining hidden Java concepts. I’ll extend the story in the next article to understand more concepts. I hope you’ll enjoy it.

Abstract Class

Master Oogway – the wise old turtle, is an abstract class who has an abstract method fight. Every master has to find their techniques to fight. In Java, an abstract method needs to be implemented compulsorily by the sub-classes (notice that I didn’t use the word “child” for sub-class). If a sub-class doesn’t want to implement an abstract method, it can also declare the method as abstract so it’s sub-classes can implement them. But in this case, it also needs to be abstract.

Instance reference

Though Master Oogway wants their type to develop fighting skill, he never fights himself. Hence, no one can request him to create his images or instances (you can consider it a child). This is the same as we can’t instantiate an abstract class in Java. However, a newly trained master may take the reference of his master or master of master for initial fightings until he gains some confidence.

1
Oogway ninjaTurtle = new Po(); //Referenced by master class

This is not only to gain confidence, but it’s always good if the master is used as a reference and use the skills of any student as per need. Eg Po can use his skills to defeat the enemy and Tigress can use her skills. But Master Shifu can use skills of both;

1
2
Shifu fighter = new Po();
Po fighter = new Shifu(); //Not allowed

📌 Info

A student can’t be a reference for his master

When we write a post on a blog, we define categories and tags. These are the markers to group particular type of posts. Though they define the type of post, they are still marker not the class. A post is a type of blog-page. A blog-page can be a type of web-page and so on.

📌 Info

I use “marker” in most of the places in this article to “Interface”.

Interface

A marker can have some default implementation of instructions to reduce the work overload on new Masters or masters with different skill. For example, some masters are the warrior but some are the teacher of secret skills. There are people in the temple who are not even the master but they help to manage other work of the temple. Sometimes, in their absence, suppose an invigilator, a master who is marked as an invigilator as well, can give extra hands if available. These masters need not to be specialized and can cope with default skills already defined by Marker. Same as Java interface may have a default implementation of a method.

java interface

The person who is in-charge of villager training might be surprised when he saw a warrior image (or instance) to perform the duty of invigilator. Without going in the complexity of a warrior, the in-charge person can use the expected skill of invigilator given by the Marker. But this is possible only if this skill is public. Hence, Java interface methods are supposed to be public. The all other methods which are private are just the supporter methods for default implementation.

1
2
3
4
5
6
7
8
9
10
11
12
interface Invigilator {
    private void checkId() {}
    private void checkAttendance() {}

    default void startExam() {
        checkId();
        checkAttendance();
        System.out.println("Starting exam...");
    }
}
:
Invigilator nonExperinced = new Tigress(); // Tigress implements Invigilator 

Interface vs Abstract class

This is worth noticing that Oogway represents a class of his own type. Since he is abstract, he can instruct his types (sub-classes) to implement some mandatory skills just like a Marker (or Interface) does. But if he will provide the default implementation of the mandatory skill then the other master may ignore the importance of the mandatory skill they should develop. Hence, in Java, markers support default implementation for a method a class should implement but an abstract class doesn’t. However, there can be some skills a master class has and a type class can override it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
abstract class Oogway {
    public void reducePressure(){
        System.out.println("Meditate");
    }
}

class Shifu extends Oogway {
    public void reducePressure(){
        System.out.println("Balance on toe");
    }
}

class Po extends Shifu {
    public void reducePressure(){
        System.out.println("Eat momos!!");
    }
}


public class Main {
    public static void main(String[] args) {
        Oogway firstTimeFighter = new Po();
        firstTimeFighter.reducePressure(); // "Eat momos!!"
        
        Shifu secondTimeFighter = new Po();
        secondTimeFighter.reducePressure(); // "Eat momos!!"
        
        Shifu experiencedFighter = new Shifu();
        experiencedFighter.reducePressure(); // "Balance on toe"
    }
}

It’s obvious that some of the villagers are confused between the importance of being abstract or marker. Are you one of the villagers!? 😂

Let me take a chance to clear up that confusion. A marker (or interface) can be considered a lightweight abstract solution. An image of some master can play multiple roles due to the markers. Since a marker is a light-weight solution, it can’t be instantiated but can be used as reference purposes only. Since they can’t be instantiated, they can’t have instance variables and the variables they have are supposed to be public, static and final. Because without public, they can’t be used. Without static, they can’t be used as no instance. Without final, their state can be changed but the state will be changed which can cause inconsistency. So an interface creates very less memory footprint. Note that the methods implemented in an interface can create instance variables.

Using public, static, final keywords with the variable in an Interface is optional.

The importance of abstract class

A master with a marker seems similar to an abstract master. But there are some meaningful differences;

  • A master (class) with a marker (interface) can be instantiated but an abstract master can’t be. An abstract master can be considered as a guide. Or a template may be.
  • Since an abstract class is like a concrete class without the ability to be instantiated, a method can even an abstract method too. This is how the template pattern is implemented;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
abstract class Oogway {

    public abstract boolean साम();
    public abstract boolean दाम();
    public abstract boolean दन्ड();
	public abstract boolean भेद();

    public boolean protectTheTemple() {
        if(!साम() && !दाम() && !दन्ड() && !भेद()); return false else return true;
    }
}

abstract class Shifu extends Oogway {
	public boolean साम(){
		return true;
	}
    public abstract boolean दाम();
    public boolean दन्ड(){
	    return true;
    }
	public abstract boolean भेद();
}

class TaiLung extends Shifu {
	public boolean दाम(){
		return true;
	}
	public boolean भेद(){
		return true;
	}
}

public class BattelField{
	public static void main(String[] args) {
		Oogway fighter = new TaiLung();
		System.out.println(fighter.protectTheTemple());
	}
}

In above example, I used unicode just for an example. But Java supports unicode in String value from Java 12.

In other words, we can say that when Oogway can fight with the skills of Tai Lung, Oogway is abstract.

Interface default methods

It doesn’t matter If there are 2 markers having a common method because the skill implemented by a master is supposed to be used further. But if more than 1 marker has a default method then the master can’t ignore it as it will create confusion. So the master is supposed to implement the skill otherwise the battle, I mean your application will not even start.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
interface PhonixFire {
    public default void fly() {
        System.out.println("I'm flying!");
    }
}

interface EagalEye {
    public default void fly() {
        System.out.println("I fly high");
    }
}

interface Po implements PhonixFire, EagalEye{
    public default void fly() {
        System.out.println("I afraid to fly but will learn to ride the weapon which can fly");
    }
}

Remember that if Master Shifu is marked as Trainer, Po doesn’t become trainer automatically. Po also need to be marked as Trainer explicitly. Means Po needs to implement Trainer interface.

Shadowing

In the last article, Master Shifu explained Po with the metaphor of lanterns that if a sub-type declares a variable with the same name his master used, then the value of sub-type will shadow the value of master.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Master{
    final int x= 10;
    static int y= 10;
    int z= 10;
}

class Subtype extends Master{
    int x= 20;
    static int y= 20;
    int z= 20;
}

public class Main {

    public static void main(String[] args) throws Exception {
        
       Master a = new Master(); 
       System.out.println(a.x);//10
       System.out.println(a.y);//10
       System.out.println(a.z);//10
       
       Subtype b = new Subtype(); 
       System.out.println(b.x);//20
       System.out.println(b.y);//20
       System.out.println(b.z);//20
       
       Master c = new Subtype();
       System.out.println(c.x);//10
       System.out.println(c.y);//10
       System.out.println(c.z);//10
    }
}

In Java, when a subclass declares a variable with the same name as a variable in its superclass, the subclass variable “hides” or shadows the superclass variable. This means that when accessing the variable through a reference of the superclass type, the superclass variable will be used, regardless of the actual object’s type.

Dynamic method dispatch or late binding

But there is a twist; If you use a reference of the Master class but call a method of the Subtype class that uses the variables, the method will still use the variables of the Subtype class. This behavior is determined at runtime and is known as dynamic method dispatch or late binding.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Master {
    final int x = 10;
    static int y = 10;
    int z = 10;
    
    public void printVariables() {
        System.out.println(x);
        System.out.println(y);
        System.out.println(z);
    }
}

class Subtype extends Master {
    int x = 20;
    static int y = 20;
    int z = 20;

    @Override
    public void printVariables() {
        System.out.println(x);
        System.out.println(y);
        System.out.println(z);
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        Master c = new Subtype();
        c.printVariables();  // Calls the overridden method in Subtype
    }
}

Output

1
2
3
20
20
20

Note that we’re not using printVariables of Master class in above example but still declared it as we’re calling printVariables using the reference of Master class. Thought printVariables of Subtype would be called but if printVariables is not present in Master class then it’ll throw error at runtime: error: cannot find symbol.

📌 Info

When you use Master class as reference, all the methods and variables that you call via the reference variable must present in master class.

Method Overriding and shadowing

  • A static method can be shadowed by the subtype
  • A final method can’t be overriden. Hence, gives error
  • Normal methods are overriden by subtype
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Master {
    static int m() {return 10;}
     int m1() {return 10;}
}

class Subtype extends Master {
    static int m() {return 20;}
     int m1() {return 20;}
}

public class Main {
    public static void main(String[] args) throws Exception {
        Master a = new Master();
        Subtype b = new Subtype();
        Master c = new Subtype();
        c.printVariables();  // Calls the method of Subtype class

        System.out.println(a.m()); //10
        System.out.println(b.m()); //20 //Shadowing
        System.out.println(c.m()); //10 

        System.out.println(a.m1()); //10
        System.out.println(b.m1()); //20 //Overriding
        System.out.println(c.m1()); //20 //Overriding
    }
}

In easy words, you can say overriding is a kind of shadowing that happens when child class implement the same method of parent class.

1
2
3
4
5
6
7
8
public class ShadowingExample {
    private int num = 10; // Class-level variable

    public void shadowMethod() {
        int num = 20; // Local variable shadowing the class-level variable
        System.out.println("Local variable num: " + num); // Prints the value of the local variable
    }
}

I hope I have covered all the concepts. I explained in the original story.



Your feedback is really important. So I can improve my future articles and correct what I have already published. You can also suggest if you want me to write an article on particular topic. If you really like this blog, or article, please share with others. That's the only way I can buy time to write more articles.

Amit
Amit Author & Maintainer of many opensourse projects like fast-xml-parser, imglab, stubmatic etc. Very much interested in research & innovations.

Related Articles

Story of Kungfu Java Valley
Chapter 2: The Preparation of Battle
Amir Wishu Sehgal cafe: The story of opportunities