欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java开发笔记(五十)几种开放性修饰符

程序员文章站 2022-11-21 21:48:46
前面介绍子类继承父类的时候,提到了public(公共)和private(私有)两个修饰符,其中public表示它所修饰的实体是允许外部访问的;而private表示它所修饰的实体不允许外部访问,只能在当前类内部访问private成员,即便是子类也不能访问父类的私有成员。这种情况就令人产生了困惑,私人财 ......

前面介绍子类继承父类的时候,提到了public(公共)和private(私有)两个修饰符,其中public表示它所修饰的实体是允许外部访问的;而private表示它所修饰的实体不允许外部访问,只能在当前类内部访问private成员,即便是子类也不能访问父类的私有成员。这种情况就令人产生了困惑,私人财产当然不会给外人,可是为啥连儿子都无法动用老子的财物呢?看起来public与private的规则不甚合理,毕竟儿子同外人还是有区别的呀,所谓亲疏有别、一家人不说两家话。为此java设计了新的修饰符名叫protected,意思是受保护的,其实就是给子类们网开一面,凡是被protected修饰的成员,外部仍然不可访问,唯有从当前类派生而来的子类可以访问。那么对于受保护的成员来说,它对外部而言如同私有成员一样不能访问,它对子类而言如同公共成员一样能够访问。
当然,引入protected不仅仅是面子上好看,还带来了实实在在的好处。比如之前编写鸭子类继承鸟类的时候,发现性别名称字段需要由“雄/雌”改为家禽通用的“公/母”,当时尝试了下列的两种写法:
1、在duck类里面重新定义与父类同名的属性字段sexname,这样没有变更外部对sexname的访问权限,但是需要重写与该字段有关的所有方法。
2、把bird类的sexname改为使用public修饰,此时新的鸭子类duckpublic无需全部重写相关方法,但同时外部变得能够直接读写sexname字段,从而破坏了原来bird类对该字段的良好封装。
既要保持外部的访问权限不变,又要避免子类冗余的方法重载,这两个愿景看似鱼与熊掌不可兼得。现在有了修饰符protected,原本自相矛盾的问题立马迎刃而解,具体的解决步骤说明如下:
首先给bird类的sexname属性添加protected修饰,表示该字段是受保护的成员属性,只可在本家族内部使用,不可对外部开放。于是改写后的bird类代码片段如下所示:

public class bird {

	// 此处省略其它成员的定义……
	
	// 定义鸟的性别名称
	//private string sexname; // 与duck搭配使用
	//public string sexname; // 与duckpublic搭配使用
	protected string sexname; // 与duckprotected搭配使用
	
	// 此处省略其它成员的定义……
}

接着编写与之配套的鸭子类代码duckprotected,并重载setsextype方法,将sexname字段的取值改为“公”或者“母”。详细的duckprotected类定义代码示例如下:

// 演示关键字protected的用法
public class duckprotected extends bird {

	public duckprotected(string name, int sex) {
		super(name, sex, "嘎嘎");
	}

	public void setsextype(int sextype) {
		super.setsextype(sextype);
		// 若想对父类的属性直接赋值,又不想对外开放该属性,则可将父类的属性从private改为protected
		// 被protected修饰的成员,表示受保护,它允许子类访问,但不允许外部访问。
		// 倘若父类的属性被protected修饰,则子类可以直接读写该属性;
		// 倘若父类的方法被protected修饰,则子类可以直接读写该方法;
		// 所谓读方法,就是方法的调用操作;所谓写方法,就是方法的重载操作。
		sexname = (sextype==0) ? "公" : "母";
		//super.sexname = (sextype==0) ? "公" : "母";
	}
}

注意,被protected修饰的成员属性,对于子类来说可读可写,既能把原值读出来也能把新值写进去。然而被protected修饰的成员方法,又何来所谓的读写操作?确实,方法不像字段,它没有读方法和写方法的概念,只有方法调用和方法重载的说法。那么对于方法而言,方法调用可看作是一种读操作,而方法重载可看作是一种写操作,瞅瞅“重写”二字带着一个“写”字嘛。

从公共的public,到私有的private,再到受保护的protected,正好三个单词都以字母p开头,3p系列这下总算凑齐了吧?可是还有一种情况,就是某个实体不加任何的开放性修饰符。嗯哼,java居然允许某个东西既非公共又非私有也非受保护,那这东东究竟要给谁使用?不加修饰符的话,其实java也给它分配了一个默认的开放性,譬如某人在美国出生,他便自动获得了美国国籍;某人在北京出生,理应要获得北京户口,这个国籍或户口即可看成是默认的归属地。拥有北京户口的人,可以优先享受当地的教育、医疗等资源,为的就是他/她是北京人,所以当地资源对他/她够友好。在java的编程世界之中,“当地”指的是同一个package(代码包),既然大家生活在同一个package的屋檐下面,就应当互相帮助互相爱护。因而未加3p修饰符的实体,表示它属于当地资源,对当地人很友好,凡是有当地户口的都允许访问它。
如此算来,java实际上存在四种开放性,根据开放程度的大小排序,依次分别为:
public:公共的,允许所有人访问;
无修饰符:友好的,允许当地人访问;
protected:受保护的,允许本家族访问,包括自身及其子类;
private:私有的,只有自身可以访问。



更多java技术文章参见《java开发笔记(序)章节目录