封装
将对象的转态信息隐藏在对象内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对内部信息的访问和操作。
封装的好处:
- 隐藏类的实现细节
- 使用者只能通过事先预定的方法来访问数据,从而可以在该方法里加入控制逻辑,限制对成员变量的不合理访问。
- 可进行数据检查从而有利于保证对象信息的完整性
- 便于修改,提高代码的科维护性
具体实现方式:
使用 private 修饰符把成员变量设置为私有,防止外部程序直接随意调用或修改成员变量,然后对外提供 public 的 set 和 get 方法来设置和获取成员变量的值。
Java 中主要有 private、protected、public 和 默认访问权限四种:
- private(当前类访问权限):如果类里面的一个成员(包括成员变量,方法和构造器等)使用private访问控制符来修饰,则这个成员只能在当前类的内部被访问。用于修饰成员变量最合适就可以将其隐藏在该类内部。
- default(包访问权限):如果类里面的一个成员(包括成员变量,方法和构造器等)或者一个外部类不使用任访问控制修饰符,就成他为包访问权限的,default访问控制的成或外部类可以被相同包下的其他类访问
- protected(子类访问权限):如果类里面的一个成员(包括成员变量,方法和构造器等)使用protected访问控制符来修饰,那这个成员既可以被同一包中的其他类 访问,也可以被不同包中的子类访问。通常是希望其子类来重写这个方法
- public(公共访问权限):这个类里面的一个成员(包括成员变量,方法和构造器等)或者一个外部类使用public访问控制符来修饰,那么这个成员或外部类就可以被所有的类访问,不管访问和被访问类是否处于同一个包中,是否具有父子继承关系。
访问控制级别如下表:
例子:
public class Person {
//使用private修饰成员变量,将这些变量隐藏起来
private String name;
private int age;
//提供方法来操作name成员变量
public void setName(String name) {
//执行合理性校验,要求名字必须在2~6之间
if (name.length()>6 || name.length()<2){
System.out.println("设置的名字不符合要求");
return;
}else{
this.name=name;
}
}
public String getName() {
return name;
}
//提供方法来操作gae成员变量
public void setAge(int age) {
//执行合理性校验,要求年龄必须在0~100之间
if (age>100 || age<0){
System.out.println("设置的年龄不符合要求");
return;
}else{
this.age=age;
}
}
public int getAge() {
return age;
}
}
继承
继承概念
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。java继承通过extends关键字来实现,实现继承的类被称为子类(基类),被继承的类被称为父类(超类)。
生活中的继承:
兔子和羊属于食草动物类,狮子和豹属于食肉动物类。
食草动物和食肉动物又是属于动物类。
所以继承需要符合的关系是:is-a,父类更通用,子类更具体。
虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。
类的继承格式
class 父类{
}
class 子类 extends 父类{
}
为什么要继承
接下来我们通过实例来说明这个需求。
开发动物类,其中动物分别为老虎以及豹子,要求如下:
- 老虎:属性(姓名,id),方法(吃,睡,自我介绍)
- 豹子:属性(姓名,id),方法(吃,睡,自我介绍)
老虎:
public class Tiger{
private String name;
private int id;
public Tiger(String myName, int myid) {
name = myName;
id = myid;
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是" + id + "号" + name + ".");
}
}
豹子:
public class Leopard{
private String name;
private int id;
public Leopard(String myName, int myid) {
name = myName;
id = myid;
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是" + id + "号" + name + ".");
}
}
从这两段代码可以看出来,代码存在重复了,导致后果就是代码量大且臃肿,而且维护性不高(维护性主要是后期需要修改的时候,就需要修改很多的代码,容易出错),所以要从根本上解决这两段代码的问题,就需要继承,将两段代码中相同的部分提取出来组成 一个父类:
食肉动物类:
public class Carnivore{
private String name;
private int id;
public Carnivore(String myName, int myid) {
name = myName;
id = myid;
}
public void eat(){
System.out.println(name+"正在吃");
}
public void sleep(){
System.out.println(name+"正在睡");
}
public void introduction() {
System.out.println("大家好!我是"+ id + "号" + name + ".");
}
}
这个Carnivore类就可以作为一个父类,然后老虎类和豹子类继承这个类之后,就具有父类当中的属性和方法,子类就不会存在重复的代码,维护性也提高,代码也更加简洁,提高代码的复用性(复用性主要是可以多次使用,不用再多次写同样的代码) 继承之后的代码:
继承后的老虎:
public class Tiger extends Carnivore{
public Tiger(String myName, int myid) {
super(myName, myid);
}
继承后的豹子:
public class Leopard extends Carnivore{
public Tiger(String myName, int myid) {
super(myName, myid);
}
super和this有什么区别?
super是一个关键字,代表父类的存储空间标识。(可以理解为父亲的引用)
super和this的用法相似。
this代表对象的引用(谁调用就代表谁);
super代表当前子类对父类的引用。
继承的优点和缺点
优点:
- 提高了代码的复用性
- 提高了代码的维护性
- 建立了类与类之间的关系,继承是多态的前提。
缺点:
- 在一定程度上,造成类与类之间的强关联,即所谓的高耦合。
- 父类功能的改变对子类也会造成影响。
注意事项:
Java 不支持多继承,下面是错误的:
如果想实现A和B里面的方法可以用implements实现:
多态
多态是同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作,如图所示:
多态是对象的多种变现形式的体现:
现实生活中,比如“叫”这个动作:
猫的“叫”:“喵喵喵~”
狗的“叫”:“汪汪汪~”
giao哥的“叫”:“一给我的giaogiao~”
同一个事件发生在不同的对象上会产生不同的结果
多态的优点
- 消除类型之间的耦合关系
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性
多态存在的三个必要条件
- 继承
- 重写
- 父类引用指向子类对象
比如:
Parent p = new Child();
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
例子:
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
Animal a = new Cat(); // 向上转型
a.eat(); // 调用的是 Cat 的 eat
Cat c = (Cat)a; // 向下转型
c.work(); // 调用的是 Cat 的 work
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat)a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
}
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}
执行以上程序,输出结果为:
吃鱼
抓老鼠
吃骨头
看家
吃鱼
抓老鼠
多态的实现方式
-
重写:详细可访问:Java 重写(Override)与重载(Overload)
-
抽象类和抽象方法:详细可访问:抽象类和抽象方法
-
接口:生活中的接口最具代表性的就是插座,例如一个三接头的插头都能接在三孔插座中,因为这个是每个国家都有各自规定的接口规则,有可能到国外就不行,那是因为国外自己定义的接口类型
java中的接口类似于生活中的接口,就是一些方法特征的集合,但没有方法的实现。详细可访问:接口