关于封装性的讨论:源自尚硅谷宋红康老师
面向对象的特征之一:封装于隐藏
一、问题引入:
当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象的属性赋值。这里的赋值操作收到属性
数据类型和存储范围的制约。但是除此之外,没有其他制约条件,但是,实际问题中,我们往往需要给属性赋值,添加
额外的限制条件。这个条件不能在属性声明时体现(不能对属性直接进行if ,else)我们只能通过方法限制条件的添加。
比如(setLegs),同时需要避免用在使用"对象.属性"进行赋值。则需要将属性声明为私有的(private)
此时,针对此属性的操作,视作封装性。
二、封装性的体现:
我们将类的属性xxx私有化(private),同时,提供公共的(public )方法来获取(getXxx)和设置(setXxx)
拓展:封装性的体现——1)如上,2)不对外暴露私有的方法,3)单例模式...
三、封装性的体现,需要权限修饰符来配合。
1. java规定的4中权限(从小到大排列):private 、缺省(特别是缺省,英文单词时default,但是不要写出来,写出来是错误 的,)、protected、public
2. 4种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类
3. 具体的,4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类
修饰类的话:只能使用 :缺省 、public
第一步实现,类的完整展示:
package prectice;
/**
* 面向对象特征之一:封装与隐藏 简称::封装性。
* 介绍:为什么需要封装,封装的作用和含义?
* 我要用洗衣机,只需要按一下开关和洗涤模式就可以了,不必要了解洗衣机内部的结构,不必要碰电动机。
* 我要开车,只需要....
*
* 开发原则: 高内聚低耦合
* 高内聚(类的内部数据操作细节自己完成,不允许外部干涉) 低耦合(仅对外暴露少量的方法用于使用)
*
* 隐藏对象内部的复杂性,之对外公开简单的接口。方便外接调用,从而提高系统的可扩展性、可维护性。
* 通俗的说:把该隐藏的隐藏起来,该暴露的暴露出来,——即封装性的设计思想。
*
* @author ZZ1299
*
*/
//本类讲的就是怎么不对外暴露,用权限设置实现
public class AnimalTest {
public static void main(String[] args){
Animal a = new Animal();
a.name = "大黄";
a.age = 1;
a.legs = 4;
a.show();//通过对象调用show方法,show方法中有Animal 的属性,谁调用的show方法,这个属性就是谁的
}
}
class Animal{
String name;
int age;
int legs;//腿的个数
public void eat(){
System.out.println("动物进食");
}
public void show(){
System.out.println("name = "+name+ ",age="+ age +",legs="+legs);
}
}
第二步:需求更改:
如果想把 legs 改成 -4 ,违背客观规律,但是第一段代码的写法是允许的,如下文
package prectice;
/**
* 面向对象特征之一:封装与隐藏 简称::封装性。
* 介绍:为什么需要封装,封装的作用和含义?
* 我要用洗衣机,只需要按一下开关和洗涤模式就可以了,不必要了解洗衣机内部的结构,不必要碰电动机。
* 我要开车,只需要....
*
* 开发原则: 高内聚低耦合
* 高内聚(类的内部数据操作细节自己完成,不允许外部干涉) 低耦合(仅对外暴露少量的方法用于使用)
*
* 隐藏对象内部的复杂性,之对外公开简单的接口。方便外接调用,从而提高系统的可扩展性、可维护性。
* 通俗的说:把该隐藏的隐藏起来,该暴露的暴露出来,——即封装性的设计思想。
*
* @author ZZ1299
*
*/
//本类讲的就是怎么不对外暴露,用权限设置实现
public class AnimalTest {
public static void main(String[] args){
Animal a = new Animal();
a.name = "大黄";
a.age = 1;
a.legs = 4;
a.show();//通过对象调用show方法,show方法中有Animal 的属性,谁调用的show方法,这个属性就是谁的
a.legs =-4;
a.show();//实际上是不可以有-4条腿。可以作为一个限制条件。但是我们又不可以在属性上进行修改。
//要怎么进行限制,可以考虑用方法来限制。
}
}
class Animal{
String name;
int age;
int legs;//腿的个数
public void eat(){
System.out.println("动物进食");
}
public void show(){
System.out.println("name = "+name+ ",age="+ age +",legs="+legs);
}
}
第三步:改进
package prectice;
/**
* 面向对象特征之一:封装与隐藏 简称::封装性。
* 介绍:为什么需要封装,封装的作用和含义?
* 我要用洗衣机,只需要按一下开关和洗涤模式就可以了,不必要了解洗衣机内部的结构,不必要碰电动机。
* 我要开车,只需要....
*
* 开发原则: 高内聚低耦合
* 高内聚(类的内部数据操作细节自己完成,不允许外部干涉) 低耦合(仅对外暴露少量的方法用于使用)
*
* 隐藏对象内部的复杂性,之对外公开简单的接口。方便外接调用,从而提高系统的可扩展性、可维护性。
* 通俗的说:把该隐藏的隐藏起来,该暴露的暴露出来,——即封装性的设计思想。
*
* @author ZZ1299
*
*/
//本类讲的就是怎么不对外暴露,用权限设置实现
public class AnimalTest {
public static void main(String[] args){
Animal a = new Animal();
a.name = "大黄";
a.age = 1;
a.legs = 4;
/**
* 学习顺序,这里是测试阶段,第二个阶段
*/
a.show();//通过对象调用show方法,show方法中有Animal 的属性,谁调用的show方法,这个属性就是谁的
// a.legs =-4;
a.setLegs(6);//把 a.legs =-4修改成 a.legs =6___________实验得到:输出legs = 6
//如果把 a.setLegs(6); 改成-6 则输出为 0
a.show();//实际上是不可以有-4条腿。可以作为一个限制条件。但是我们又不可以在属性上进行修改。
//要怎么进行限制,可以考虑用方法来限制。
}
}
class Animal{
String name;
int age;
int legs;//腿的个数
/**
* 学习顺序,这里是第一阶段,改了这里的if语句在改 public static void main(String[] args)
* 中 的 a.setLegs(6); 语句
*
* @param l
*/
//做一个设置属性的方法:这个方法要有形参,这个形参作为赋值,代入值到属性中。
public void setLegs(int l){//这里把 l 赋值给 属性 int legs 。
//legs = l;//相当于,谁调用这个setLegs方法,谁就填入了一个l,然后 l 赋给 调用此方法的legs 的属性。
//因此,上一行的语句可以改成我们的逻辑: l 大于等于零, 而且,是一个偶数
if(1>=0 && 1%2 ==0){
legs =l;
}else {
legs = 0;
//或者不等于零,抛出一个异常。
}
}
public void eat(){
System.out.println("动物进食");
}
public void show(){
System.out.println("name = "+name+ ",age="+ age +",legs="+legs);
}
}
第四步:属性还是可以设置,如下文:
package prectice;
/**
* 面向对象特征之一:封装与隐藏 简称::封装性。
* 介绍:为什么需要封装,封装的作用和含义?
* 我要用洗衣机,只需要按一下开关和洗涤模式就可以了,不必要了解洗衣机内部的结构,不必要碰电动机。
* 我要开车,只需要....
*
* 开发原则: 高内聚低耦合
* 高内聚(类的内部数据操作细节自己完成,不允许外部干涉) 低耦合(仅对外暴露少量的方法用于使用)
*
* 隐藏对象内部的复杂性,之对外公开简单的接口。方便外接调用,从而提高系统的可扩展性、可维护性。
* 通俗的说:把该隐藏的隐藏起来,该暴露的暴露出来,——即封装性的设计思想。
*
* @author ZZ1299
*
*/
//本类讲的就是怎么不对外暴露,用权限设置实现
public class AnimalTest {
public static void main(String[] args){
Animal a = new Animal();
a.name = "大黄";
a.age = 1;
a.legs = 4;
/**
* 学习顺序,这里是测试阶段,第二个阶段
*/
a.show();//通过对象调用show方法,show方法中有Animal 的属性,谁调用的show方法,这个属性就是谁的
// a.legs =-4;
a.setLegs(6);//把 a.legs =-4修改成 a.legs =6___________实验得到:输出legs = 6
//如果把 a.setLegs(6); 改成 a.setLegs(-6); 则输出为 0
//第四部分:属性的权限问题还是没解决:如下
a.legs = -4;
/**
* 这里,编译器没有报错,并且可以运行。怎么办呢?? 设置权限。
* 在class Animal 类中的变量设置权限,把int legs 加上private。
*/
a.show();//实际上是不可以有-4条腿。可以作为一个限制条件。但是我们又不可以在属性上进行修改。
//要怎么进行限制,可以考虑用方法来限制。
}
}
class Animal{
String name;
int age;
/**
* 声明完 private 之后
* 类中的 public static void main(String[] args) a.legs = -4; 将报错
* The field Animal.legs is not visible 这个属性不可见 但是,堆空间中依然有这个属性。
*
* 这个属性不对外开放了
*/
private int legs;//腿的个数
/**
* 学习顺序,这里是第一阶段,改了这里的if语句在改 public static void main(String[] args)
* 中 的 a.setLegs(6); 语句
*
* @param l
*/
//做一个设置属性的方法:这个方法要有形参,这个形参作为赋值,代入值到属性中。
public void setLegs(int l){//这里把 l 赋值给 属性 int legs 。
//legs = l;//相当于,谁调用这个setLegs方法,谁就填入了一个l,然后 l 赋给 调用此方法的legs 的属性。
//因此,上一行的语句可以改成我们的逻辑: l 大于等于零, 而且,是一个偶数
if(1>=0 && 1%2 ==0){
legs =l;
}else {
legs = 0;
//或者不等于零,抛出一个异常。
}
}
public void eat(){
System.out.println("动物进食");
}
public void show(){
System.out.println("name = "+name+ ",age="+ age +",legs="+legs);
}
}