[PYTHON] I looked into class inheritance overrides.

Introduction

My junior asked me about Java class inheritance, but I couldn't answer it immediately, so I did a lot of research.

Origin

Old @IT Conference Room: About Variable Inheritance

Excerpt because it is difficult to read

When a variable with the same name exists in the superclass, the method of the superclass When executed, the variable with the same name referred to the superclass. How can I refer to the variable with the same name in my class?

Below is a sample source. What I thought would return "I am a child" returned "I am a parent."

Main.java


//Execution class
public class Main{
    public static void main(String args[]){
        Child c1 = new Child();
        c1.print(); 
    } 
} 

//Super class
class Parent{
    private String JIBUN = "parent"; 
    public void print(){
        System.out.println("I" + JIBUN + "is."); 
    }
} 

//Child class
class Child extends Parent{
    private String JIBUN = "children";
}

He said that he didn't understand even if he read the explanation.

Java inheritance and overloading

The moment I saw it, I thought that JIBUN is private, so it can't be referenced from other classes, and Parent and Child are different, right? It was that.

But what if it's protected (public)? I came up with the question, so I investigated it properly.

Below is the source used for the test. piza.io

Main.java



//Execution class
public class Main{
    public static void main(String args[]){
        Child c1 = new Child();
        c1.print(); 
        c1.print2();
        Parent parent = new Child();
        c1.print(); 
        c1.print2();
    } 
} 

//Super class
class Parent{
    private String JIBUN1 = "Parent 1"; 
    protected String JIBUN2 = "Parent 2"; 
    protected String JIBUN3 = "Parent 3"; 
    public void print(){ 
        System.out.println("print"); 
        System.out.println("I" + JIBUN1 + "is."); 
        System.out.println("I" + JIBUN2 + "is."); 
        System.out.println("I" + JIBUN3 + "is."); 
    }
//    final public void print2(){If you don't want to override it, add final and you will get a compile error.
    public void print2(){
        System.out.println("print2"); 
        System.out.println("Parents" + JIBUN1 + "is."); 
        System.out.println("Parents" + JIBUN2 + "is."); 
        System.out.println("Parents" + JIBUN3 + "is."); 
    } 
} 

//Child class
class Child extends Parent{
    // @Override //Compile error because it cannot be overridden
    private String JIBUN1 = "Child 1";
    // @Override //Compile error because it cannot be overridden
    protected String JIBUN2 = "Child 2";
    Child() {
        this.JIBUN3 = "Child 3";
    }
    @Override //Override annotation clearly states that it is an override
    public void print2(){
        System.out.println("print2"); 
        System.out.println("Children" + JIBUN1 + "is."); 
        System.out.println("Children" + JIBUN2 + "is."); 
        System.out.println("Children" + JIBUN3 + "is."); 
    } 
}

Execution result

print
I am parent 1.
I am parent 2.
I am 3 kids
print2
The child is child 1.
The child is child 2.
The child is child 3.
print
I am parent 1.
I am parent 2.
I am 3 kids
print2
The child is child 1.
The child is child 2.
The child is child 3.

The results are summarized below.

About C # inheritance and overloading

Actually, I originally learned object-oriented programming in C #, so it was easier to write.

piza.io

This time, there are method overrides and hiding, so there are print2 (override) and print3 (hiding).

Main.cs


using System;

public class Test {
    public static void Main(){
        Child c1 = new Child(); 
        c1.print(); 
        c1.print2(); 
        c1.print3(); 
        Parent parent = new Child(); 
        parent.print(); 
        parent.print2(); 
        parent.print3(); 
    }
}

//Super class
public class Parent{
    // virtual //Compile error because it cannot be overridden
    private string JIBUN1 = "Parent 1"; 
    // virtual //Compile error because it cannot be overridden
    protected string JIBUN2 = "Parent 2"; 
    // virtual //Compile error because it cannot be overridden
    protected string JIBUN3 = "Parent 3";
    public void print(){ 
        Console.WriteLine("print"); 
        Console.WriteLine("I" + JIBUN1 + "is."); 
        Console.WriteLine("I" + JIBUN2 + "is."); 
        Console.WriteLine("I" + JIBUN3 + "is."); 
    } 
    virtual public void print2(){ 
        Console.WriteLine("print2"); 
        Console.WriteLine("Parents" + JIBUN1 + "is."); 
        Console.WriteLine("Parents" + JIBUN2 + "is."); 
        Console.WriteLine("Parents" + JIBUN3 + "is."); 
    }
    public void print3(){
        Console.WriteLine("print3"); 
        Console.WriteLine("Parents" + JIBUN1 + "is."); 
        Console.WriteLine("Parents" + JIBUN2 + "is."); 
        Console.WriteLine("Parents" + JIBUN3 + "is."); 
    } 
} 

//Child class
public class Child : Parent{ 
    // override //Compile error because it cannot be overridden
    private string JIBUN1 = "Child 1";
    // override //Compile error because it cannot be overridden
    protected string JIBUN2 = "Child 2";
    public Child() {
        this.JIBUN3 = "Child 3";
    }
    override public void print2(){
        Console.WriteLine("print2"); 
        Console.WriteLine("Children" + JIBUN1 + "is."); 
        Console.WriteLine("Children" + JIBUN2 + "is."); 
        Console.WriteLine("Children" + JIBUN3 + "is."); 
    }
//    override public void print3(){Compile error because print3 does not have virtual
    public void print3(){ //Just an overwrite definition
        Console.WriteLine("print3"); 
        Console.WriteLine("Children" + JIBUN1 + "is."); 
        Console.WriteLine("Children" + JIBUN2 + "is."); 
        Console.WriteLine("Children" + JIBUN3 + "is."); 
    } 
}

Output result

print
I am parent 1.
I am parent 2.
I am 3 kids
print2
The child is child 1.
The child is child 2.
The child is child 3.
print3
The child is child 1.
The child is child 2.
The child is child 3.
print
I am parent 1.
I am parent 2.
I am 3 kids
print2
The child is child 1.
The child is child 2.
The child is child 3.
print3
The parent is parent 1.
The parent is parent 2.
Parent is child 3.

Compile error (warning)

Compilation succeeded - 2 warning(s)
Main.cs(49,22): warning CS0108: `Child.JIBUN2' hides inherited member `Parent.JIBUN2'. Use the new keyword if hiding was intended
Main.cs(21,22): (Location of the symbol related to previous warning)
Main.cs(60,17): warning CS0108: `Child.print3()' hides inherited member `Parent.print3()'. Use the new keyword if hiding was intended
Main.cs(36,17): (Location of the symbol related to previous warning)

The results are summarized below.

Well, that feeling was cultivated in C #, so it's an individual impression.

About C ++ inheritance and overloading

I haven't coded C ++ seriously, so I'll try to google it.

There are also print2 and print3 here.

paiza.io

Main.cpp


#include <iostream>
using namespace std;

//Super class
class Parent{
    private:
        // virtual //Compile error because it cannot be overridden
        string JIBUN1 = "Parent 1";
    protected:
        // virtual //Compile error because it cannot be overridden
        string JIBUN2 = "Parent 2"; 
        // virtual //Compile error because it cannot be overridden
        string JIBUN3 = "Parent 3";
    public:
        void print() {
            cout << "print" << endl;
            cout << "I" + JIBUN1 + "is." << endl;
            cout << "I" + JIBUN2 + "is." << endl;
            cout << "I" + JIBUN3 + "is." << endl;
        };
        virtual void print2() {
            cout << "print2" << endl;
            cout << "Parents" + JIBUN1 + "is." << endl;
            cout << "Parents" + JIBUN2 + "is." << endl;
            cout << "Parents" + JIBUN3 + "is." << endl;
        }
        void print3() {
            cout << "print3" << endl;
            cout << "Parents" + JIBUN1 + "is." << endl;
            cout << "Parents" + JIBUN2 + "is." << endl;
            cout << "Parents" + JIBUN3 + "is." << endl;
        }
};

//Child class
class Child : public Parent{ 
    private:
        string JIBUN1 // override //Compile error because it cannot be overridden
        = "Child 1";
    protected:
        string JIBUN2 // override //Compile error because it cannot be overridden
        = "Child 2";
        
    public:
        Child() {
            this->JIBUN3 = "Child 3";
        };
        void print2() override {
            cout << "print2" << endl;
            cout << "Children" + JIBUN1 + "is." << endl;
            cout << "Children" + JIBUN2 + "is." << endl;
            cout << "Children" + JIBUN3 + "is." << endl;
        }
        // void print3() override {Compile error because print3 does not have virtual
        void print3() { //Just an overwrite definition
            cout << "print3" << endl;
            cout << "Children" + JIBUN1 + "is." << endl;
            cout << "Children" + JIBUN2 + "is." << endl;
            cout << "Children" + JIBUN3 + "is." << endl;
        }
};

int main(void){
    Child *c1 = new Child();
    c1->print();
    c1->print2();
    c1->print3();
    Parent *parent = new Child();
    parent->print();
    parent->print2();
    parent->print3();
}

Execution result

print
I am parent 1.
I am parent 2.
I am 3 kids
print2
The child is child 1.
The child is child 2.
The child is child 3.
print3
The child is child 1.
The child is child 2.
The child is child 3.
print
I am parent 1.
I am parent 2.
I am 3 kids
print2
The child is child 1.
The child is child 2.
The child is child 3.
print3
The parent is parent 1.
The parent is parent 2.
Parent is child 3.

There were no particular compilation errors (warnings).

The results are summarized below.

About inheritance and overload of python3

I also investigated the LL language at this time. The class is python that looks like a retrofit.

Since the assumptions are different, the source has quite different meanings. sorry. (JIBUN1 and JIBUN2 are class fields)

There are print2 and print3 here as well, but they are the same because they cannot be written separately.

paiza.io

main.py


# coding: utf-8
# Your code here!

def main():
    c1 = Child()
    c1.print()
    c1.print2()
    c1.print3()

    parent = Parent()
    parent.print()
    parent.print2()
    parent.print3()

#Super class
class Parent(object):
    JIBUN1 = "Parent 1"
    JIBUN2 = "Parent 2"
    def __init__(self):
        self.JIBUN3 = "Parent 3"
        
    def print(self):
        print("print")
        print("I" + self.JIBUN1 + "is.")
        print("I" + self.JIBUN2 + "is.")
        print("I" + self.JIBUN3 + "is.")

    def print2(self):
        print("print2")
        print("Parents" + self.JIBUN1 + "is.")
        print("Parents" + self.JIBUN2 + "is.")
        print("Parents" + self.JIBUN3 + "is.")

    def print3(self):
        print("print3")
        print("Parents" + self.JIBUN1 + "is.")
        print("Parents" + self.JIBUN2 + "is.")
        print("Parents" + self.JIBUN3 + "is.")
 

#Child class
class Child(Parent):
    JIBUN1 = "Child 1"
    def __init__(self):
        super(Parent, self).__init__()
        self.JIBUN3 = "Child 3"

    def print2(self):
        print("print2")
        print("Children" + self.JIBUN1 + "is.")
        print("Children" + self.JIBUN2 + "is.")
        print("Children" + self.JIBUN3 + "is.")

    def print3(self):
        print("print3")
        print("Children" + self.JIBUN1 + "is.")
        print("Children" + self.JIBUN2 + "is.")
        print("Children" + self.JIBUN3 + "is.")

if __name__ == '__main__':
    main()

Execution result

print
I am a child 1.
I am parent 2.
I am 3 kids
print2
The child is child 1.
The child is parent 2.
The child is child 3.
print3
The child is child 1.
The child is parent 2.
The child is child 3.
print
I am parent 1.
I am parent 2.
I'm parent 3
print2
The parent is parent 1.
The parent is parent 2.
The parent is parent 3.
print3
The parent is parent 1.
The parent is parent 2.
The parent is parent 3.

The results are summarized below.

Well, it feels easy to understand.

About inheritance and overload of ruby

Even in the LL language, ruby seems to have designed the class from the beginning, so for reference. ruby I just scratched it a little.

This is also a source with a quite different meaning.

paiza.io

Main.rb


# coding: utf-8
# Your code here!

def main()
    c1 = Child.new
    c1.print
    c1.print2
    Child.print3

    parent = Parent.new
    parent.print
    parent.print2
    Parent.print3
end

#Super class
class Parent
    @JIBUN1 = "Parent 1"
    @@JIBUN2 = "Parent 2"
    def initialize
        @JIBUN3 = "Parent 3"
    end
        
    def print
        p "print"
        p "I" + (@JIBUN1 || 'undefined') + "is."
        p "I" + (@@JIBUN2 || 'undefined') + "is."
        p "I" + @JIBUN3 + "is."
    end

    def print2
        p "print2"
        p "Parents" + (@JIBUN1 || 'undefined') + "is."
        p "Parents" + (@@JIBUN2 || 'undefined') + "is."
        p "Parents" + @JIBUN3 + "is."
    end

    def self.print3
        p "print3"
        p "Parents" + @JIBUN1 + "is."
        p "Parents" + @@JIBUN2 + "is."
        p "Parents" + (@JIBUN3 || 'undefined') + "is."
    end
end
 

#Child class
class Child < Parent
    @JIBUN1 = "Child 1"
    @@JIBUN2 = "Child 2"
    def initialize
        super
        @JIBUN3 = "Child 3"
    end

    def print2
        p "print2"
        p "Children" + (@JIBUN1 || 'undefined') + "is."
        p "Children" + (@@JIBUN2 || 'undefined') + "is."
        p "Children" + @JIBUN3 + "is."
    end

    def self.print3
        p "print3"
        p "Children" + (@JIBUN1 || 'undefined') + "is."
        p "Children" + (@@JIBUN2 || 'undefined') + "is."
        p "Children" + (@JIBUN3 || 'undefined') + "is."
    end
end

main

Execution result

"print"
"I am undefined."
"I am 2 kids"
"I am 3 kids"
"print2"
"Children are undefined."
"The child is child 2."
"The child is child 3."
"print3"
"The child is child 1."
"The child is child 2."
"Children are undefined."
"print"
"I am undefined."
"I am 2 kids"
"I'm parent 3"
"print2"
"The parent is undefined."
"The parent is child 2."
"The parent is parent 3."
"print3"
"The parent is parent 1."
"The parent is child 2."
"The parent is undefined."

The results are summarized below.

It seems that it was designed with classes, but it is a mystery why class variables and class instance variables became like this.

Summary

Recommended Posts

I looked into class inheritance overrides.
Class inheritance
[Python] Class inheritance (super)
[Python] Class inheritance, override
[Django] I tried to implement access control by class inheritance.
5 reasons I got into Python
Class inheritance and super functions