Java封装——访问权限控制

探讨程序设计中类创建者与客户端程序员的角色,介绍如何通过合理设计避免类更新带来的影响,重点讲解Java访问权限修饰词的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

预备术语

若将程序开发人员按照角色分类,可以分为以下两类:

类创建者

那些创建新数据类型的程序员。

客户端程序员

那些在其应用中使用类创建者提供的数据类型的类消费者。
注:客户端程序员也可以是类创建者:他在类库的设计中用到了其他程序员创建的类,同时他也将提供新的数据类型给其他类消费者。

前言

通常一个优秀的作者可能会反复的修改其作品,以使得其著作越来越完美(没有绝对的完美,希望读者不要纠结于完美这个用词),这也是为什么很多著作都会有第一版、第二版、第三版等等。
同理,一个优秀的类设计者也需要反复的修改他所创建的类,使其越来越完美。然而,有时类创建者的修改,对于一些客户端程序员可能是一场灾难。
例如,这些类消费者在其应用中大量的使用到了类的某个(或某些)方法,而类创建者在某次更新版本后声明:以前的那个方法存在极大的缺陷,现已增加了一个全新的方法替代了那个方法(甚至可能以前的方法直接被删除了),新的方法不仅避免了缺陷,更极大的提升了效率。

以下代码展示了一个具体的例子:
注:“//:”表示一个文件的开头,“//:~”表示这个文件的结尾。因此,以下代码可能不止在一个文件中。

//: Design.java —— 类设计者创建的类(新版)
public class Design {
	// 旧的有缺陷的方法
	void method() {
		//some code...
	}
	// 新的避免缺陷且更有用的方法
	void moreUserful() {
		//some code...
	}
}
//:~

//: App.java —— 客户端程序员创建的应用(大量使用了旧版的方法)
public class App {
	public static void main(String[] args) {
		//some code...
		Design d1 = new Design();
		Design d2 = new Design();
		Design d3 = new Design();
		d1.method();
		d2.method();
		d3.method();
		//some code...
	}
}
//:~

那么此时,这些客户端程序员该怎么做呢?
一,继续使用老版本的类,同时承受缺陷所带来的所有风险(这在多数情况下显然是不明智的)。
二,使用新版本的类,并把应用中所有的旧版方法修改为新版中新增的方法,根据应用大小,修改成百上千甚至上万的方法,都是有可能的(好吧,可能某位负责任的程序员在把所有方法都修改好后就直接下岗,并决定再也不从事该行业了)。
显然,无论哪个选择,都不是那么令人满意。
实际上,这是一个设计时的缺陷。一个合理的解决方案是:类创建者在设计时专门对外提供一个方法供类消费者使用,这个方法调用了任何随时可能修改的其它方法。并且跟类消费者约定好:只能用这个对外提供的方法,其它方法不要使用。

以下代码展示了改进的例子,以及在这个例子中类创建者的更改对客户端程序员的影响。

//: SmarterDesign.java —— 类设计者创建的类(新版)
public class SmarterDesign {
	// 约定好的对外提供的方法
	void provide() {
		// method();
		/* 在新版中注释掉了旧版调用了方法,
		 * 使用了新的更可靠的方法,然而此时
		 * 只要客户端程序员遵守约定,是不会
		 * 对其原来的代码产生影响的:
		 * 他们不需要修改任何原来的代码就能
		 * 享有新版的特性,只需要将SmarterDesign
		 * 文件替换为新版即可。
		 */
		moreUseful();
	}
	// 旧的有缺陷的方法
	void method() {
		//some code...
	}
	// 新的避免缺陷且更有用的方法
	void moreUseful() {
		//some code...
	}
}
//:~

//: App2.java —— 客户端程序员创建的应用(大量使用了与类创建者约定好的对外提供的方法)
public class App2 {
	public static void main(String[] args) {
		//some code...
		SmarterDesign d1 = new SmarterDesign();
		SmarterDesign d2 = new SmarterDesign();
		SmarterDesign d3 = new SmarterDesign();
		d1.provide();
		d2.provide();
		d3.provide();
		//some code...
	}
}
//:~

可以看到,在这个例子中,只要大家都遵守约定,不管SmarterDesign的创建者以后如何修改provide()中调用的方法,都不会对客户端程序员原先的代码结构产生影响。
这个设计仍然存在一个问题:设计者的良苦用心是否起效在于使用者是否遵守约定。然而,可能会有某个(甚至某些)客户端程序员并不知道这些约定(可能他们没有仔细看设计者提供的文档),或者在开发的过程中忘了有这么回事,那么可能设计者的好心就白费了。
好在Java语言中有访问权限修饰词,它们能很好的处理这类问题:只要类创建者合理的使用了它们,那么不管是类创建者还是客户端程序员都不必那么费心了,这些修饰词会替我们好好的处理这些麻烦。

Java访问权限修饰词

Java访问权限修饰词在使用时,置于类中每个成员的定义之前。每个访问权限修饰词仅控制它所修饰的特定定义的访问权,以下是各种修饰词所定义的访问权。

public

使成员成为公共的成员,无论是谁,无论在哪里,都可以访问该成员。

默认的包访问权

本文以上所有示例中的大多数成员都没有使用任何访问权限修饰词,这些成员默认的拥有包访问权,即同一个包中任何地方都能访问到该成员。

protected

使成员成为受保护的成员,该成员只有在本类、本类的子类以及同一个包中可以被访问。也就是说,protected修饰的成员同时拥有包访问权。

private

使成员成为私有的成员,该成员只有在本类中可以被访问。

回到问题

让我们回顾之前SmarterDesign的例子,利用修饰词,类创建者只需将需要对外提供的成员修饰为public的(例子中的provide()),将需要隐藏的实现修饰为private的(例子中的method()和moreUseful()),即可避免以后修改(甚至是删除)隐藏的实现对客户端程序员的代码结构造成影响。

*练习

请读者尝试给SmarterDesign例子中的成员添加合适的修饰词,来达到类设计者预期的效果(相信这对您而言并不是一件难事)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值