前言
面向对象(OOP)与面向过程(POP)
- 二者都是一种思想,面向对象是相对于面向过程而言的。面向过程,强调的是功能行为。面向对象,将功能封装进对象,强调具备了功能的对象。
- 面向对象更加强调运用人类在日常的思维逻辑中采用的思想方法与原则,如抽象、分类、继承、聚合、多态等。
面向对象的三个特征
- 封装 (Encapsulation)
- 继承 (Inheritance)
- 多态 (Polymorphism)、
下面我们就来理解一下面向对象的三个特征吧
一、封装
1.定义:
- 封装是指隐藏对象的属性和实现细节,仅仅对外提供接口。要访问该类的代码和数据,必须通过严格的接口控制。
- 封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
2.优点:
- 有助于建立各个系统的耦合关系,提高系统独立性。某个系统的实现发生变化,只要它的接口不变,就不会影响其他系统。
- 提高软件的重用性。
3.java 提供的四种访问控制级别:
- public:对外公开,访问级别最高。
- protected:只对同一个包中的类或者子类公开。
- 默认:只对同一个包中的类公开。
- private: 不对外公开,只能在对象的内部访问,访问级别最低。
4.封装的两个大致原则:
1.把尽可能多的东西藏起来,对外提供简单的接口。
系统的封装程度越高,它的相对独立性就越高。
举个例子:就像半自动与全自动洗衣机。半自动洗衣机需要防水、洗涤、排水等过程,而全自动洗衣机中封装了洗衣的各项步骤,留出开机的接口。
2.把所有的属性隐藏
Java中通过将数据声明为私有的(private),再提供公共的(public)方法:getXxx()和setXxx()实现对该属性的操作。
// A code block
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private int age;
采用 this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。
还可以防止访问者错误的修改属性
// A code block
if(age<=0||age>=130){
System.out.println("输入的年龄不正确");
}
else{
this.age=age;
}
二、继承
java语言中用extends关键字来表示一个类继承另一个类。
public class C extends hero{
...
}
1.为什么要有继承?
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
2.此处的多个类称为子类,单独的这个类称为父类(基类或超类)。可以理解为:“子类 is a 父类”
3.作用:
- 一个子类只能有一个父类
- 继承的出现提高了代码的复用性。
- 继承的出现让类与类之间产生了关系,提供了多态的前提。\
- 不要仅为了获取其他类中某个功能而去继承
4.Java只支持单继承,不允许多重继承
- 一个子类只能有一个父类
- 一个父类可以派生出多个子类
class A extends C{
} //ok
class A extends C1,C2...{
} //error
1. 方法重载(Overload)
例1
public void train(Dog dog){
//训练小狗
}
public void train (Cat cat){
//训练小猫
}
例2
public Person7(String name){
this();
this.name=name;
}
public Person7(int age,String name) {
this(1);
this.age=age;
this.name=name;
重载方法必须满足的条件
- 方法名相同。
- 方法的参数类型、个数、顺序至少有一项不相同。
- 方法的返回类型可以不相同。
- 方法的修饰符可以不相同。
2. 方法重写/覆盖(Override)
定义:在子类中可以根据需要对从父类中继承来的方法进行改造,也称方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。
要求:
- 重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值类型。
- 重写方法不能使用比被重写方法更严格的访问权限。
- 重写和被重写的方法须同时为static的,或同时为非static的子类方法抛出的异常不能大于父类被重写方法的异常
public class Person {
public String name;
public int age;
public String getInfo() {
return "Name: "+ name +"\n" +"age: "+ age;
}
}
public class Student extends Person {
public String school;
public String getInfo() { //重写方法
return "Name: "+ name + "\n +" age: "+ age +"\n +" school: "+ school ;
}
public static void main(String args[]){
Student s1=new Student();
s1.name="Bob";
s1.age=20;
s1.school="school2";
System.out.println(s1.getInfo()); //Name:Bob
age:20 school:school2
}
}
**注意:**子类方法不能缩小父类方法发访问权限.
public class A{
public void method(){...
}
public class B extends A{
private void method(){...
//error 子类方法缩小了父类的访问权限
}
方法覆盖至存在于子类和父类(包括直接子类和间接父类)之间。在同一个类方法中只能被重载,不能被覆盖。
三、多态
1.多态性,是面向对象中最重要的概念,多态是同一个行为具有多个不同表现形式或形态的能力。
2.在java中有两种体现:
- 方法的重载(overload)和重写(overwrite)。
- 对象的多态性 ——可以直接应用在抽象类和接口上。
3.java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。
- 若编译时类型和运行时类型不一致,就出现多态(Polymorphism)
4.多态存在的三个必要条件
- 继承
- 重写
- 父类引用指向子类对象
注意:在多态中,编译看左边,运行看右边
Person p = new Person();
Person e = new Student(); // Person类型的变量e,指向Student类型的对象
- 子类可看做是特殊的父类,所以父类类型的引用可以指向子类的对象:向上转型(upcasting)。
Animal animal =new Dog();
Dog dog=(Dog)animal;//向下转型,把Animal类型转化为Dog类型
Creature creature=animal;//向上转型,把Animal类型转化为Creature类型
其中向下转型,必须通过强制类型转换Dog dog=(Dog) animal
注意:
1).一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法
Student m = new Student();
m.school= “pku”; //合法,Student类有school成员变量
Person e = new Student();
e.school= “pku”; //非法,Person类没有school成员变量
属性是在编译时确定的,编译时e为Person类型,没有school成员变量,因而编译错误
2)假如两种类型之家没有继承关系,不允许强制转化
Dog dog =new Dog();
Cat cat=(Cat) dog;//error 不允许把Dog引用类型转化为Cat引用类型
5.instanceof 操作符
x instanceof A:检验x是否为类A的对象,返回值为boolean型。
- 要求x所属的类与类A必须是子类和父类的关系,否则编译错误。
- 如果x属于类A的子类B,x instanceof A值也为true。
public class Person extends Object {…}
public class Student extends Person {…}
public class Graduate extends Person {…}
-------------------------------------------------------------------
public void method1(Person e) {
if (e instanceof Person) //处理Person类及其子类对象
if (e instanceof Student) //处理Student类及其子类对象
if (e instanceof Graduate) //处理Graduate类及其子类对象
}
参考资料:
链接: java之封装继承多态.
链接: java 封装、继承、多态.
[1]孙卫琴,JAVA面向对象编程,点子工业出版社,2017