文章目录
- 封装
- 继承
- 为什么会有继承?
- 继承的特性
- 继承关键字
- 1. extends关键字
- 2. implements关键字
- 3. super与this关键字
- 多态
- 重写
- 回顾
上篇我们只是简单的说了一下类与对象,当提到面向对象,我们就会想到3个词,封装、继承、多态。
封装
封装就是一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。封装的目的是为了防止该类的代码和数据被外部类定义的代码随机访问。如果我们要访问该类代码,需要通过严格的接口控制。封装其实就是为了在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
重点:对象代表什么,就得封装对应的数据,并提供数据对应的行为。
示例:
public class Person{
private String name;//private修饰保证数据的安全性,使name属性变为私有,只能在本类中被访问
private int age;//private修饰保证数据的安全性,使age属性变为私有,只能在本类中被访问
}
public Person(){//空参构造
}
public Person(String name,int age){//带全部参数的构造
this.name=name;//this关键字——解决实例变量与局部变量重名的情况
this.age=age;
}
//对应的getter和setter方法
public int getAge(){//返回age的值
return age;
}
public void setAge(int age){//对私有变量age进行赋值
this.age = age;
}
public String getName(){//返回name的值
return name;
}
public void setName(String name){//对私有变量name进行赋值
this.name = name;
}
}
继承
首先我们就来看一看“继承”,我们在刷视频时可能会看到某个争夺家产的电视剧场景,而他们的目的是为了继承家产,就是把父亲的东西拿来自己用,这也就凸显出了继承一个特点,java不支持多继承,但支持多重继承,我们上图来看一看:
由图可知:在现实生活中图1.3的情况一般是不会发生的,同样在java中是不支持多继承的。
我们还可以看一下下面这幅图:
看图中的父类“动物”,它相比于子类“食草动物”和“食肉动物”更加的通用,它包含了各种动物,而子类相当于父类更加地具体,有自己的范围。食草动物和食肉动物虽然都是动物,但是两者中属性和行为是有所差别的,所以子类会具有父类的一般特性,同时,子类也会具有自身的特性。
类继承的格式:
class 父类{ } class 子类 extends 父类{ }
为什么会有继承?
我们想就算有相同的代码片段,那我多写几次不就行了,一次不行写两次,两次不行写三次,但是我们是否想过重复代码过多会造成什么后果,首先,肯定就是代码量大,消耗内存,臃肿;其次,如果后期需要对代码进行维护,那么成本就上来了,我们就需要修改大量代码。当我们使用继承,把类中部分的属性和方法提取到父类当中,这些问题也就解决了。
继承的特性
优点:
🍥为了代码的安全,我们使用private修饰属性与方法,由于private修饰后只能在当前类的内部使用,所以这些被private修饰的属性与方法不能够被子类所继承。
🍥儿子可以有父亲没有的东西,即子类可以拥有自己的属性与方法,也就是说子类可以对父类进行扩展。
🍥子类可以用自己的方式实现父类的方法。
🍥java的继承是单继承,但是也可以多重继承。
缺点:
代码之间的联系越紧密,代码独立性越差。
继承关键字
1. extends关键字
一个子类只能有一个父类
2. implements关键字
虽然说在java中不能实现多继承,但是我们可以通过implements关键字变相地使java具有这种特性。使用的范围为类继承接口的情况。
public interface A {
public void eat();
public void sleep();
}
public interface B {
public void show();
}
public class C implentments A,B {
}
3. super与this关键字
super关键字:通过super关键字可以实现对父类成员的访问,用来引用当前对象的父类。
this关键字:指向自己的引用
举例:
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void eatTest() {
this.eat(); // this 调用自己的方法
super.eat(); // super 调用父类方法
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Dog d = new Dog();
d.eatTest();
}
}
运行结果:
animal : eat
dog : eat
animal : eat
多态
多态是同一个行为具有不同的表现形式或形态的能力。
比如说我们生活中的打印机,分为彩色和黑白,但是两者的都是打印,只是使用的对象不同。
同一个事件发生在不同对象上会产生不同的结果。
多态存在的三个必要条件:
🍥继承
🍥重写
🍥父类引用指向子类对象:Father f=new Child();
多态的优势:
🍥消除类型之间的耦合关系
🍥可替换性
🍥可扩充性
🍥接口性
🍥灵活性
🍥简化性
代码示例:
//父类
class Shape {
void draw() {}
}
//子类
class Circle extends Shape {
void draw() {
System.out.println("Circle.draw()");
}
}
//子类
class Square extends Shape {
void draw() {
System.out.println("Square.draw()");
}
}
//子类
class Triangle extends Shape {
void draw() {
System.out.println("Triangle.draw()");
}
}
调用不同的draw方法:
重写
当子类对象调用重写的方法时,调用的是子类的方法,而不是父类中被重写的方法。
要想调用父类中被重写的方法,则必须使用关键字super。
代码示例:
class Animal{
public void move(){
System.out.println("动物在跑");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗在跑");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 对象
Animal b = new Dog(); // Dog 对象
//b是属于Animal类型,但b是Dog 的对象
a.move();// 执行 Animal 类的方法
b.move();//执行 Dog 类的方法
}
}
如果b的引用类型Anmial中没有bark方法,而Dogs中有bark方法,在运行时会发生报错。
方法重写的规则:
🍥参数列表与被重写方法的参数列表必须完全相同。
🍥返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类。
🍥访问权限不能比父类中被重写的方法的访问权限更低。
🍥父类的成员方法只能被它的子类重写。
🍥声明为 final 的方法不能被重写。
🍥声明为 static 的方法不能被重写,但是能够被再次声明。
🍥子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
🍥子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
🍥重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的 强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
🍥构造方法不能被重写。
🍥如果不能继承一个类,则不能重写该类的方法。
Super关键字的使用
代码示例:
class Animal{
public void move(){
System.out.println("动物在跑");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗在跑");
super.move();//调用super类的方法,即Anmial类中的move方法
}
}
public class TestDog{
public static void main(String args[]){
Animal b = new Dog(); // Dog 对象
//b是属于Animal类型,但b是Dog 的对象
b.move();//执行 Dog 类的方法
}
运行结果:
重写与重载的区别:
🍥方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
🍥方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
🍥方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
区别点 | 重载(同类同名不同参) | 重写(同参同名不同类) |
参数列表 | 必须修改 | 不能修改 |
返回值类型 | 可以修改 | 不能修改 |
异常 | 可以修改 | 可以减少或删除,一定不能抛出新的或者更广的异常 |
访问 | 可以修改 | 一定不能做更严格的限制(可以降低) |
多态实现的方式:重写和接口
回顾
🍥为什么会有继承?
🍥继承的优缺性?
🍥多态条件?
🍥重写与重载?