面向对象的三大特性—封装 继承 多态
一.封装
-
我们设计程序一般要追求高内聚,低耦合
高内聚:就是类的内部数据操作细节自己完成,不允许外部干涉
低耦合:仅暴露少量的方法给外部使用
-
封装:
英文为(encapsulation),即数据的隐藏。
通常应禁止直接访问一个对象中数据的实际表示,而应通过方法操作接口来访问,这称为信息隐藏。
简单来说封装可以这样理解, 属性私有(关键字private)后,提供public的可以操作这些属性的方法,方法为get和set方法
快捷键为:Alt+insert
-
封装的作用:
-
提供程序的安全性,保护数据
-
隐藏代码的实现细节
-
统一接口
-
增加系统的可维护性
-
代码示例如下:
package com.lu.OOP1.encapsulation;
//encapsulation 封装
public class Pet {
private String breed; //属性私有 在Test类创建对象后,用pet.breed直接调用会报错
private int weight;
private int age;
private char sex;
//提供一些可以操作这些属性的方法
//用public的get和set方法
//获得这个数据的方法
public String getBreed() {
return this.breed;
}
//设置这个数据的方法
public void setBreed(String breed) {
this.breed = breed;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
if (age > 12 || age < 0) { //保证合法性
System.out.println("输入的年龄不正确");
} else {
this.age = age;
}
}
}
main()方法中
package com.lu.OOP1.encapsulation;
public class Test {
public static void main(String[] args) {
Pet dog = new Pet(); //创建dog对象
dog.setBreed("狗"); //通过方法调用私有breed属性
System.out.println(dog.getBreed());
dog.setAge(10); //通过方法调用私有age属性
System.out.println(dog.getAge());
}
}
二.继承
1.继承的意义
继承是类与类的一种关系。除此之外,类与类之间的关系还有依赖,组合,聚合等。
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。即子类继承父类 。
子类继承父类,使用关键字extends来表示。子类就会拥有父类全部的方法和属性。
public class Son extends Father{··· ···}
代码示例如下:
子类:
package com.lu.OOP1.extend.a;
public class Son extends Father{
}
父类:
package com.lu.OOP1.extend.a;
public class Father/* extends Object */{
//父类的属性
private String surname;//姓
private int property = 10_0000_0000; //属性 一般private再用get set方法
//父类的方法
public void height(){ //方法一般public
System.out.println("长得很高");
}
//对属性封装数据
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public int getProperty() {
return property/2;
}
}
main()方法中:
package com.lu.OOP1.extend.a;
public class Test {
public static void main(String[] args) {
Son son = new Son(); //子类可以调用到父类的方法和属性
son.height();
son.setSurname("欧阳");
System.out.println("儿子的姓:"+son.getSurname());
System.out.println("儿子得到的财产;"+son.getProperty());
}
}
2. Object类
在Java中,Object类是默认存在的,所有类都直接或间接继承Object类 在IDEA中可用 Ctrl+h 查看继承关系
public class Father/* extends Object */{...}
public class Son/* extends Object */{...}
3. super关键字
子类继承父类后,要在子类中进行操作,就要用到关键字super
this. 表示对本类的属性和方法的调用,this()和thIs(参) 表示对本类无参构造和有参构造的调用
super只能出现在子类的属性,方法和构造器中,表示对父类属性,方法和构造器的调用
-
super对父类属性的调用
super.
-
super对父类方法的调用
super.
-
super对父类构造器的调用
super()表示对父类无参构造的调用
super(参)表示对父类有参构造的调用
注意:
super()默认调用,不显示定义出来它也存在。它和this()的位置都在构造器主体的第一条语句
super()和this()不能同时出现
代码示例如下:
父类中:
package com.lu.OOP1.extend.sup;
public class Father {
public String surname = "lu";//父类的姓
protected String name = "lu1";//定义父类属性
public void print(){//定义父类方法
System.out.println("father");
}
//父类构造器
public Father() {
System.out.println("调用Father无参构造");
}
public Father(int a) {
System.out.println("调用Father有参构造");
}
}
子类中:
package com.lu.OOP1.extend.sup;
//子类继承了父类。就会拥有父类的全部方法
public class Daughter extends Father {
public String surname = super.surname;//在子类属性中调用父类属性
private String name = "lu2"; //定义子类的属性
public void print() { //定义子类的方法
System.out.println("daughter");
}
//测试1方法 在方法中子类对父类属性的调用
public void test1(String name) {
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
//测试2方法 在方法中子类对父类方法的调用
public void test2() {
print();//daughter
this.print();//daughter
super.print();//father
}
//子类构造器对父类构造器的调用
public Daughter() {
//隐藏了super();位置必须是构造器主体中第一条语句
System.out.println("调用Daughter无参构造");
}
public Daughter(int b) {
super(1); //调用父类有参构造
System.out.println("调用Daughter有参构造");
}
}
在main()方法中
public static void main(String[] args) {
Daughter daughter = new Daughter(); //输出结果是:调用Father无参构造,调用Daughter无参构造
System.out.println(daughter.surname);//子类调用父类的属性
daughter.test1("lu3"); //对 test1方法的调用
System.out.println("--------------");
daughter.test2(); //对 test2方法的调用
Daughter daughter1 = new Daughter(1); //对子类构造器的调用
//输出结果是:调用Father有参构造,调用Daughter有参构造
}
4.方法重写
方法重写:就是在子类中重写父类的方法,与属性无关
重写后的子类方法与父类保持一致:
- 它们都为非静态方法
- 方法名和参数列表相同,方法体不同
- 修饰词范围可以扩大,但是不能缩小,一般都写成public(修饰词的优先级 public>protected>default>private )
为什么要方法重写:有的时候父类的功能,子类不一定需要,或者不一定满足
快捷键:Alt+insert
代码示例如下:
父类中
package com.lu.OOP1.extend.override;
public class People {
public void test0(){
System.out.println("输出父类的方法");
}
}
子类中
package com.lu.OOP1.extend.override;
public class GoodPeople extends People {
@Override //注解;有功能的注释
public void test0() {
System.out.println("输出子类的方法");
}
}
三.多态
多态:即同一方法可以根据发送对象的不同而采用各种不同的行为方式
多态是方法的多态,属性没有多态
一个对象的实际类型是确定的,但是可以指向对象的引用类型却有很多
1.实现多态的条件
- 有继承关系
- 子类重写父类的方法
- 父类引用指向子类对象 例 Parent parent = new Child();
代码示例如下:
父类中:
package com.lu.OOP1.polymorphic;
public class Parent {
public void methodParent(){
System.out.println("输出父类的方法");
}
//重写方法
public void test(){
System.out.println("输出父类");
}
}
子类中:
package com.lu.OOP1.polymorphic;
public class Child extends Parent {
public void methodChild(){
System.out.println("输出子类的方法");
}
//重写方法
@Override
public void test() {
System.out.println("输出子类");
}
}
main()方法:
public static void main(String[] args) {
//实际类型是确定的 new Child();
//但可以指向对象的引用类型有很多 Child ,Parent, Object
//父类引用指向子类对象
Child c1 = new Child();
Parent c2 = new Child();
Object c3 = new Child();
c1.methodParent(); //输出父类方法
c2.methodParent();//输出父类方法
System.out.println("-----------------");
c1.test(); //输出子类
c2.test();// 输出子类 子类重写父类的方法 会输出子类的方法
}
2.instanceof 关键字
instanceof表示:A(对象)instanceof B(类) 结果为 boolean 型
-
A和B比较之前会先判断A能不能转换成B类型,能则编译通过,反之编译不同;
编译通过后,会把A和B比较,如果A是B本类或是子类的对象,结果就是true反之就是false.
public static void main(String[] args) { //instanceof关键字 // Object > String // Object > People > BadPeople // Object > People > GoodPeople Object object = new GoodPeople(); System.out.println(object instanceof Object);//true System.out.println(object instanceof People);//true System.out.println(object instanceof GoodPeople);//true System.out.println(object instanceof BadPeople);//false System.out.println(object instanceof String);//false System.out.println("----------------------------------------------------"); People people = new GoodPeople(); System.out.println(people instanceof Object);//true System.out.println(people instanceof People);//true System.out.println(people instanceof GoodPeople);//true System.out.println(people instanceof BadPeople);//false //System.out.println(people instanceof String); 编译报错 System.out.println("----------------------------------------------------"); GoodPeople goodPeople = new GoodPeople(); System.out.println(goodPeople instanceof Object);//true System.out.println(goodPeople instanceof People);//true System.out.println(goodPeople instanceof GoodPeople);//true // System.out.println(goodPeople instanceof BadPeople);编译报错 // System.out.println(goodPeople instanceof String);编译报错 System.out.println("----------------------------------------------------"); }
3.类型转换
我们知道,在没有多态的情况下,父类的对象去直接调用子类的方法会报错
因此,在Java里面提供了类型转换也可以让父类的对象去调用子类的方法
父类中:
package com.lu.OOP1.polymorphic;
public class People {
public void father(){
System.out.println("输出父类方法");
}
}
子类中:
package com.lu.OOP1.polymorphic;
public class GoodPeople extends People{
public void son(){
System.out.println("输出子类方法");
}
}
main()中:
public static void main(String[] args) {
//类型转换
GoodPeople g1 = new GoodPeople();
People g2 = new GoodPeople();
//g2.son();父类对象调用子类方法会报错
//强制类型转换 高转低(父类转子类)
((GoodPeople) g2).son();//相当于GoodPeople g3 = (GoodPeople) g2;