Java和Python覆蓋/重寫函數的比較

Override是面嚮對象語言的一個特性,在基類定義一個函數/方法,在子類中,重寫這個函數/方法,將其表現爲另一個形式,從而在繼承後,完成多態。而類屬性實際上也可以重寫。在子類中定義同樣名稱的類屬性,比如a,調用a時,就看不到基類的a了。

下面我們分別用Java和Python做一個說明,設計一個基類和一個子類,並重寫一個屬性和一個方法。

Java 文件名:SubClass.java

class BaseClass{
    int a = 1;
    public void accessOwner(){System.out.println("base.a="+a);}
}

public class SubClass extends BaseClass{
    int a = 2;
    @Override
    public void accessOwner(){
        System.out.println("sub.a="+a);
        super.accessOwner();
    }
    public void accessSuper(){System.out.println("super.a="+super.a);}

    public static void main(String args[]){
        SubClass sc1 = new SubClass();
        sc1.accessOwner();  //a=2 換行 base.a=1
        System.out.println();
        sc1.accessSuper();  //super.a=1
    }
}

輸出爲:

sub.a=2
base.a=1

super.a=1

Python

class BaseClass():
    a = 1
    @classmethod
    def test(cls):
        print("base.a=%d"%cls.a)

class SubClass(BaseClass):
    a = 2
    @classmethod
    def test(cls):
        print("sub.a=%d 注意這裏的a已經是子類的a" % cls.a)
        super(SubClass, cls).test() #now in base:1  in Python 2 or 3
        super().test()  #同樣輸出now in base:1   only in Python 3
        print("調用基類的a %d" % super().a)
    
    def check(self):
        print("check a=%d  %d"% (self.a, id(self.a)))
    
    @classmethod
    def __test__(self):
        print("hello class method")
    
    @staticmethod
    def staticfunc():
        print("static函數不調用類變量和實例變量,定義時不用self")

BaseClass.test()
print()
SubClass.test()
c = SubClass()

print("Sub.__test__")
SubClass.__test__()
#調用靜態方法示例
SubClass.staticfunc() #可以用類名調用靜態方法
c.staticfunc()  #可以用實例調用靜態方法
#調用實例
print("修改實例的a並且加一個屬性b:")
c.check()
c.a = 99
c.b = 66
print(c.a,c.b)
c.check()
print("SubClass的a仍然是:%d %d"% (SubClass.a,id(SubClass.a)))

輸出:

base.a=1

sub.a=2 注意這裏的a已經是子類的a
base.a=2
base.a=2
調用基類的a 1
Sub.__test__
hello class method
static函數不調用類變量和實例變量,定義時不用self
static函數不調用類變量和實例變量,定義時不用self
修改實例的a並且加一個屬性b:
check a=2  140727241862944
99 66
check a=99  140727241866048
SubClass的a仍然是:2 140727241862944

Python的類屬性在類方法中的調用和Java有點不同,如果使用子類的類方法test調用類屬性a,需要傳一個參數cls給方法,這時,cls.a就是子類的值了。如果只寫a或者硬是寫一個self.a,都會被認爲沒有定義。實際上,cls也可以換爲self,在這個方法定義中效果是一樣的,如果把subClass中的cls全部換成self,會看到一樣的輸出。

Python的類屬性a在實例中被重新定義後,就會生成一個新的id,用一個新指針去指向它,這跟新加一個屬性沒太大區別了。

上述例子中,原來的類屬性a id是140727241862944,重新定義後,再次調用SubClass.a可以看到仍然是這個值。但是,實例去調用a,id已經變了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章