类的私有属性和方法指的是只能在类的内部使用,而不能在类外使用的属性和方法。
1 单下划线方式
在定义类的属性和方法时,在名字前面加一个下划线,此时表示该属性或方法只能在类的内部使用,而不能在类的外部使用,代码如图1所示。
图1 定义类的私有属性
从图1中可以看出,在类Myclass中定义了两个实例变量,“a”和“_b”。其中变量“a”是公共变量,变量“_b”是私有变量;第5-8行定义了类的两个方法getb()和setb(),分别用来获取和设置变量“_b”的值。使用变量“a”和“_b”的代码如图2所示。
图2 使用变量“a”和“_b”的代码
其中,第10行实例化了Myclass类的一个实例c,对于类的公共变量“a”,可以通过第11-12的代码在类的外部进行设置和获取,而对于私有变量_b,则不能像a一样在类的外部设置和获取,而需要像代码13-14行,通过调用类的函数,在类的内部进行设置和获取。设置类的私有方法与设置类的私有变量类似,只需在方法名前加入一个下划线即可。
使用本方法设置的类的私有变量和方法只是约定俗成的,告诉代码阅读者该属性和方法是私有的,但是并不是严格的语法要求。也就是说,也可以通过像访问和设置共有属性那样访问和设置私有属性,如图3所示。
图3 像访问和设置共有属性那样访问和设置私有属性
2 双下划线方式
2.1 定义和使用私有属性的正确方法
也可以在类的属性和方法名前加入两个下划线将其设置为私有,代码如图4所示。
图4 定义类的私有属性
其中,“a”是类的共有属性,“__b”是类的私有属性,可以在getb()和setb()中获取和设置私有属性“__b”。如果在类外使用“__b”,此时程序会报错,如图4和图5所示。
图4 在类外使用私有变量“__b”的错误代码
图5 报错信息
从图4和图5中可以看出,c是Myclass类的实例,通过该实例在类外调用私有属性“__b”时,程序的报错信息是Myclass类没有“__b”属性。也就是说,在属性名前加两个下划线的方法,从语法上指定了类的私有属性。
要想在类外设置和获取私有变量“__b”,可以通过如图6所示代码。
图6 在类外使用私有变量“__b”的正确代码
getb()和setb()是类Myclass的共有方法,因此可以在类外使用,在这两个方法内部来设置和获取私有方法,从而达到在类外使用私有属性的目的。同理,也可以在方法名前加上两个下划线将其设置为私有方法。
2.2 原因分析
通过如图7所示的代码,查看实例c的属性和方法,得到的结果如图8所示。
图7 查看实例c的属性和方法的代码
图8 实例c的属性和方法
从图8②处可以看出,“a”、“getb”和“setb”分别表示实例的公共属性和公共方法,而图8①的“_Myclass__b”表示实例的私有属性“__b”。也就是说,对于前缀是两个下划线的属性,类会对其进行重命名,将“_类名”加到私有属性名之前。
相关链接1 类的这种重命名行为,叫做name mangling,也就是名称修饰,为了避免类被继承时,与子类的属性发生命名冲突。
因此,可以通过图9所示的代码访问实例的私有属性。
图9 访问实例的私有属性