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已經變了。