好久没写了,不知道是不是有默默关注我的人,因为清明放假加上赶作业,呜呜呜,好了,言归正传吧!
今天我们的目标是了解面向对象的三大特征之一,封装!
博主第一次接触封装这个词是在大学本科画电路板的时候,当时学的一脸懵逼,然后在接触Java的封装之后呢,对于理解还是有一点点帮助的。
到底什么是封装呢?简单的来讲,Java既然是一种和日常生活非常相近的面向对象的语言(人在生活中就是面向各种对象的嘛),那么我们做的就是用代码的描述尽可能的贴近日常生活。那么我们首先来看我们在第二篇文章中提到的一个例子:
import java.util.*;
public class Dog{
//我就省略构造器啦
public String dogName;
//成员变量的命名呢一般是几个英文单词连一起,第一个单词
//全小写后面单词首字母大写,叫驼峰命名法
public int age;
public void run(){
System.out.println("i can run");//还记得打印语句吗
}
public void bark(){
System.out.println("i can bark");
}
我们有了一类狗!(再说一遍博主很爱狗!)那么现在就有个问题了,假设我家里养了一只狗(这只狗就是这个类的一个实例),这只狗狗有个年龄,还有我给它起的一个漂亮名字,当然能跑能叫,看上去很完美。然而灾难的一天来了,我家来客人了,有个调皮的小孩让狗又跑又叫,一切还是很开心,但是他说,这只狗叫小丑(然而我给它起的名字是小美),它100岁(然而实际上它2岁),我很不能容忍他这样说我家的狗,可是我无能为力,因为仔细看看我们创建的这只狗,年龄和名字都是public的,也就是说,任何操作对象的人想怎么改就怎么改,这显然是不符合实际的!为了解决这一类的问题,我们就引出了封装!
封装就是说将对象的信息隐藏在对象内部,不允许外部程序直接访问对象内部的信息,而是通过该类所提供的方法来实现对内部信息的访问!
一个良好的封装主要有两个方面的,第一呢是将对象的成员变量和实现细节隐藏起来,不允许外部直接访问;第二是把方法暴露出来,让方法来控制对这些成员变量进行安全的访问和操作。
那么如何隐藏该隐藏的,暴露该暴露的呢,Java提供了访问控制符,下面就该了解他们啦。
private(当前类访问权限):如果一个类的成员使用private来修饰,那么这个成员只能在当前类被访问。很显然更我们找到了隐藏成员的方法!
default(包访问权限):也叫作默认访问权限,也就是说如果不加访问修饰符,那么系统就默认修饰符是default。被它修饰的东西可以在同一个包下面被其他类访问。
protected(子类访问权限):如果一个成员被它修饰,那么他既可以被相同包的其他类访问,也可以被不同包中的子类访问。特别的,如果用protected修饰方法,通常希望子类重写这个方法。哦哦,不知道子类,重写是什么?没关系,这是明天的内容!
public(公共访问权限):这就不用解释了吧,大家都可以访问的啦!
特别需要注意的,局部变量(定义在方法内部的变量),因为本身的作用于就是方法,所以不能使用访问修饰符!
那么关于访问修饰符,还有几个使用原则:1)类中绝大部分成员变量都该使用private修饰,只有一些static修饰的,类似全局变量的成员变量,才用public修饰。有一些方法是类自己内部用的,并不需要给别人用,这样的方法也应该用private修饰。2)希望子类重写的方法应该用protected修饰。3)希望暴露的方法用public修饰。
有个这些工具和原则,是时候把我们的狗狗变得更好啦!重新改写的狗狗如下:
import java.util.*;
class Dog{//没加修饰符,默认default!
//我就省略构造器啦
private String name;
//成员变量的命名呢一般是几个英文单词连一起,第一个单词
//全小写后面单词首字母大写,叫驼峰命名法
private int age;//成员变量,private修饰
public void setName(String name){//暴露给其他方法使用的,public修饰
this.name = name;
}
public String getName(){
return this.name;
}
public void setAge(int age){//可以在set方法中进行控制
if(age>12||age<0){
System.out.println("error!");
return;
}
else
this.age = age;
}
public int getAge(){
return this.age;
}
public void run(){
System.out.println("i can run");//还记得打印语句吗
}
public void bark(){
System.out.println("i can bark");
}
}
public class dogtest{
public static void main(String[] args){
Dog d = new Dog();
d.setAge(2);
System.out.println(d.getAge());
d.setName("小美");
System.out.println(d.getName());
d.run();
d.bark();
}
}
结果如下:
如果在dogtest中直接用d.name ,d.age 会怎么样呢?代码如下:
public class dogtest{
public static void main(String[] args){
Dog d = new Dog();
d.age = 2;
System.out.println(d.age);
d.name = "小美";
System.out.println(d.name);
d.run();
d.bark();
}
}
那么就会这样:
看,就会报访问权限的错误!!!
还有最后一个问题,可以看到在dog类中,为了其他类能够访问name和age,我们为每个private修饰的成员变量都写了getter和setter方法,在Java中,这也是实现封装最常用的办法。getter和setter方法的命名规则就是在被private修饰的成员变量首字母大写,并在前面加上get和set,比如getName()。在setter方法中,我们可以对输入的数据进行控制。
另外,如果一个java类中所有成员变量都用private修饰,并且为每个private修饰的成员变量都提供了public修饰的setter和getter方法,那么这个类就是一个符合JavaBean规范的类,这种类都是封装良好的!