一般说,在基类中定义的访问基类中属性的方法,即使派生类覆盖他也不会造成影响,没懂😂?
我的意思是这个👇 举一个简单的例子
public class Person {
private final String _name = "person";
public String getName() {
return this._name;
}
}
public class Worker extends Person {
private final String _name = "worker";
}
你应该不会疑惑当我实例化 Worker 类然后再在调用 getName 方法应该返回的是 person 吧。
但是在 py 中就不不是这样,例如:
class Person:
def __init__(self):
self._name = 'person'
def get_name(self):
return self._name
class Worker(Person):
def __init__(self):
self._name = 'worker'
# >>> w = Worker()
# >>> w.get_name()
# 'worker'
不仅是对象属性会表现出这样的特点,对于类属性(或者如果按java的叫法应该叫做静态属性)也会如此。
所以假如你在代码中做了这样的事情的话,可能会出现奇怪的问题,假使你重来没有遇到过这种问题,也算正常,毕竟在父子类中起一个重复的变量名好像没有什么特别的好处,也算不上好实践
PS;好像需要收回这句话,Django源码中经常这样做,并且在利用行为
那么接下来在来看一下猴子补丁还是以上面定义的 py 代码为例:
def get_name(self):
return 'new name'
Worker.get_name = get_name # 用 Person.get_name = get_name 也是一样滴~~
w.get_name
# >>> 'new name'
运行时改变行为,这个就叫猴子补丁
当然还有就是这边直接修改的时未绑定方法,如果修改绑定方法的话,那么就不需要 self 参数了,如
def get_name():
return 'foo'
w.get_name = get_name
w.get_name()
# >>> 'foo'
啥叫绑定(bind),啥叫未绑定呢?
可以注意到在类中定义的成员方法时候都需要传递一个 self 参数,然而在对象实例话以后成员函数的 self 参数却又不需要传递了,也就是说该对象的成员函数中的 self 参数和该对象绑定了
PS: 了解一点JS的可能觉得也不算太奇怪,因为 JS 就有 call、apply 和 bind 函数,略略略
而在类中,他们还是尚未绑定的,例如我们可以这样调用尚未绑定的方法
Person.get_name(w)
# >>> 'worker'