封装,继承和多态
上一篇主要讲了类和对象,这次我们的主要讲述面向对象的三大特性:继承,封装,多态。
首先在每个特点开始最前方我会放一下图谱,按照图谱结果开始进行逐步讲解。
封装
-
封装定义:将对象的状态信息隐藏在独享内部,不允许外部程序直接访问对象内部信息而是通过该类提供的方法来实现内部信息的操作访问。
-
封装目的:
1.隐藏类的实现细节
2.让使用者只能通过事先预定的方法来访问数据,从而可以在该方法中加入控制逻辑限制不合理访问
3.可以进行数据检查有利于数据完整性
4.便于修改,提高可维护性 -
封装如何实现:访问控制符
1.private(当前类访问权限):如果类中有成员(包括成员变量,方法,构造器)使用private来修饰那么其被隐藏在该类内部。需要修改或者使用的时候,只能调用setter()和getter()方法
2. default(包访问权限)::如果类中有成员(包括成员变量,方法,构造器)或者外部类使用default或者不使用任何控制符修饰那么它默认为default访问权限,可以在相同包中被访问
3.protected(子类访问权限):如果类中有成员(包括成员变量,方法,构造器)使用protected来修饰那么可以被不同包的子类继承,且通常希望子类重写
4.public(公共访问权限):最宽松的访问控制级别,可以被所有类访问不管是否在一个包内,是否继承。
- import关键字:前面提到了包和跨包,那么如何进行跨包操作呢?
- import 包名到目的包.*:该源文件内所有位于其中的可见包均可使用
- import 包名.类名:直接导入指定java类2.import 包名.类名:直接导入指定java类
- .import static:静态导入,可以导入类的静态成员或方法.import static:静态导入,可以导入类的静态成员或方法
-
this关键字:因为在类中偶尔会出现成员变量和局部变量同名情况,根据java的就近原则,在方法中首先匹配的是局部变量。但是我们赋值需要的是成员变量,因此我们使用this的关键字来进行指向成员变量或者成员方法
-
this.成员变量名=局部变量名
class Car {
String brand ; //品牌
String price ; //价格
//this.成员变量名=局部变量名,进行赋值
public Car(String brand,String price) {
this.brand = brand ; this.price = price ;
}
public String getInfo(){
return "品牌:" + brand + ",价格:" + price ;
}
}
public class TestDemo{
public static void main(String[] args) {
Car car = new Car("AstonMartin","900000$");
System.out.println(car.getInfo());
}
}
- this.方法名();
和上方类似只是直接调用方法
静态方法无法使用this关键字 - 方法重载:同名不同参,返回值无关
在类的内部可以有多个同名的方法,为了区别它们因此在传入的时候传入不同的参数,或者参数个数,或者参数顺序加以区别,但是返回值不能作为区别它们的方式。
class Car {
String brand ; //品牌
String price ; //价格
//this.成员变量名=局部变量名,进行赋值
public Car(String brand,String price) {
this.brand = brand ; this.price = price ;
}
public String show(String brand){
return "品牌:" + brand ;
}
public String show(String brand ,String price){
return "品牌:" + brand + ",价格:" + price ;
}
}
继承
-
继承的定义:实现软件复用的重要手段,具有单继承特带你每个子类只有一个直接父类
-
继承特点:java继承使用extends关键字实现,实现继承的类称为子类,被继承的类也称为父类,基类,超类。继承关系可以简单的理解为 “子类
is a 父类” -
例如“苹果是一种水果”而不是“水果是一种苹果”
修饰符 class
SubClass extends SuperClass{
//类定义部分
}
子类(SubClass)extends
父类(SuperClass):子类可以对付类进行扩展,可以获得父类可见的成员变量和方法
例如:苹果继承于水果
public class Fruit{
public double weight;
public void show(){
System.out.println("我是一个水果,重量为"+weight+"g");
}
}
public class Apple extends Fruit{
public static void main(String[] args){
//创建Apple对象 a
Apple a=new Apple();
//Apple本身并没有weight成员变量但是继承了父类Fruit的public修饰的成员变量
a.weight=560;
//调用show()方法
a.show();
}
}
Apple类是一个空类,只包含了一个main()方法,但是这样只能看出来继承如何体现扩展呢?我们使用方法重写和方法的添加来显示子类的扩展
- 方法重写:子类是一个特殊的父类,大多数时候子类以父类为基础,额外增加新的成员变量和方法,但是当父类和子类有不同用的表现时,父类的方法无法表示子类因此需要重写。例如:鸟类含有飞翔方法,但是企鹅不能飞翔,那么我们就需要根据子类进行重写父类的飞翔方法
public class Bird{
public void fly(){
System.out.println("在天空中飞翔");
}
}
public class Penguins extends Bird{
public void fly(){
System.out.println("我不能飞但我在地上跑,另外冲q币吗?");
}
public static void main(String[] args){
Penguins p =new Penguins();
p.fly();
}
}
可以说子类覆盖父类方法,因为现在执行时,执行子类方法。
重写需要遵循“两同两小一大”
两同:方法名相同,形参列表相同
两小:子类返回值类型小或相等,抛出异常类更小或者相等
一大:子类访问权限更大
- 添加新方法:父类的方法不足够描述子类,因此子类需要自己写方法来描述自己
- super关键字:在子类中调用父类被覆盖的方法或者父类的变量。super也不可以出现在static修饰的方法中。
例如:我们使用callOverrideMethod()方法来显示super调用父类
public void callOverrideMethod(){
super.fly()
}
虽然现在还没讲构造方法,但是在子类的构造中如果没有调用其它的父类的构造方法,那么默认调用super()来调用父类的无参构造方法。
-
final关键字:见上方图片
-
只是在这里提一下后面具体讲
- 抽象类:可以有抽象方法也可以没有,使用abstract修饰
- 接口:极端抽象类,使用interface修饰
多态
-
多态定义:是指一个引用(类型)在不同的情况下的多种状态。也可以理解为,多态是指通过指向父类的指针,来调用在不同子类中实现的方法
-
Java引用变量有两个类型:一个是编译类型,一个是运行类型。编译时类型由声明该变量的类型决定,运行时类型由实际赋值决定。当编译时类型和运行时类型不一致就称为多态。
编译看左,运行看右 -
多态前提:
1.必须有继承:子类继承父类,存在一些特点
2.必须有方法重写
3.父类指向子类对象 -
对象多态 :向上转型或者向下转型
-
方法多态
通俗的理解多态就是:父类对象调用子类的方法,但是此方法必须是在父类中也含有的方法。
例如
class Animal{
public void eat(){
System.out.println("吃饭");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("肉");
}
public void lookDoor(){
System.out.println("看门");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("鱼");
}
public void playGame(){
System.out.println("捉迷藏");
}
}
public class DuoTaiTest {
public static void main(String[] args){
//定义为狗 ,父类指向子类
Animal a = new Dog();
//因为多态因此只能调用父类中有的方法,编译看左(父类)运行看右(子类)
a.eat();
System.out.println("------------");
//还原成狗 ,进行类型转换才能够使用Dog类中自定义的方法
Dog d = (Dog) a;
d.eat();
d.lookDoor();
System.out.println("-------------");
//变成猫
a = new Cat();
a.eat();
System.out.println("-------------");
//还原成猫
Cat c = (Cat)a;
c.eat();
c.playGame();
}
}
多态牵涉到许多问题还没提及,因此我们先到此打住,等讲到那一块知识的时候继续讲多态。