java之面向对象
感谢以下博文的作者以及菜鸟编程:
https://zhuanlan.zhihu.com/p/93123305、
https://www.runoob.com/
一、面向对象的基本概念:
面向对象简称 OO(Object Oriented),20 世纪 80 年代以后,有了面向对象分析(OOA)、 面向对象设计(OOD)、面向对象程序设计(OOP)等新的系统开发方式模型的研究。
对编程语言来说,一切皆是对象。把现实世界中的对象抽象地体现在编程世界中,一个对象代表了某个具体的操作。一个个对象最终组成了完整的程序设计,这些对象可以是独立存在的,也可以是从别的对象继承过来的。对象之间通过相互作用传递信息,实现程序开发。
Java 是面向对象的编程语言,对象就是面向对象程序设计的核心。所谓对象就是真实世界中的实体,对象与实体是一一对应的,也就是说现实世界中每一个实体都是一个对象,它是一种具体的概念。对象有以下特点:
- 对象具有属性和行为。
- 对象具有变化的状态。
- 对象具有唯一性。
- 对象都是某个类别的实例。
- 一切皆为对象,真实世界中的所有事物都可以视为对象。
如何建立面向对象的思维呢?
- 先整体,再局部
- 先抽象,再具体
- 能做什么,再怎么做
二、面向对象的三大特性:
1、继承
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:
1 //类的继承格式 2 class 父类 {...} 3 class 子类 extends 父类 {...} 4 5 //当子类继承父类之后,就具有父类当中的属性和方法,子类就不会存在重复的代码,维护性也提高, 6 //代码也更加简洁,提高代码的复用性(复用性主要是可以多次使用,不用再多次写同样的代码)
继承的特性:
-
子类拥有父类非 private 的属性、方法。
-
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
-
子类可以用自己的方式实现父类的方法。
-
Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
-
提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
super 与 this 关键字:
super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
this关键字:指向自己的引用。
1 class Animal { 2 void eat() { 3 System.out.println("animal : eat"); 4 } 5 } 6 7 class Dog extends Animal { 8 void eat() { 9 System.out.println("dog : eat"); 10 } 11 void eatTest() { 12 this.eat(); // this 调用自己的方法 13 super.eat(); // super 调用父类方法 14 } 15 } 16 17 public class Test { 18 public static void main(String[] args) { 19 Animal a = new Animal(); 20 a.eat(); 21 Dog d = new Dog(); 22 d.eatTest(); 23 } 24 } 25
final关键字:
final 关键字 声明的类不能被继承,即最终类;或者用于修饰方法,该方法不能被子类重写:
-
声明类:final class 类名 {//类体}
-
声明方法:修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}
构造器:
子类是不继承父类的构造器的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。
重写与重载:
重写(Override)是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!
重载(Overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
2、多态
多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作。具体来说,就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
多态的优点:
- 1. 消除类型之间的耦合关系
- 2. 可替换性
- 3. 可扩充性
- 4. 接口性
- 5. 灵活性
- 6. 简化性
多态存在的三个必要条件:
- 继承
- 重写
- 父类引用指向子类对象:Parent p = new Child();
多态的实现的三种方式:
- 重写
- 接口
- 抽象类和抽象方法
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。以下是一个多态实例的演示,详细说明请看注释:
1 public class Test { 2 public static void main(String[] args) { 3 show(new Cat()); // 以 Cat 对象调用 show 方法 4 show(new Dog()); // 以 Dog 对象调用 show 方法 5 6 Animal a = new Cat(); // 向上转型 7 a.eat(); // 调用的是 Cat 的 eat 8 Cat c = (Cat)a; // 向下转型 9 c.work(); // 调用的是 Cat 的 work 10 } 11 public static void show(Animal a) { 12 a.eat(); 13 // 类型判断 14 if (a instanceof Cat) { // 猫做的事情 15 Cat c = (Cat)a; 16 c.work(); 17 } else if (a instanceof Dog) { // 狗做的事情 18 Dog c = (Dog)a; 19 c.work(); 20 } 21 } 22 } 23 24 abstract class Animal { 25 abstract void eat(); 26 } 27 28 class Cat extends Animal { 29 public void eat() { 30 System.out.println("吃鱼"); 31 } 32 public void work() { 33 System.out.println("抓老鼠"); 34 } 35 } 36 37 class Dog extends Animal { 38 public void eat() { 39 System.out.println("吃骨头"); 40 } 41 public void work() { 42 System.out.println("看家"); 43 } 44 } 45
执行以上程序,输出结果为:
吃鱼
抓老鼠
吃骨头
看家
吃鱼
抓老鼠
3、封装
封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据。对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法。适当的封装可以让程式码更容易理解与维护,同时也加强了程式码的安全性。
封装的优点:
-
良好的封装能够减少耦合。
-
类内部的结构可以自由修改。
-
可以对成员变量进行更精确的控制。
-
隐藏信息,实现细节。
封装的示例:
1 public class Person{ 2 //修改属性的可见性来限制对属性的访问(一般限制为private) 3 private String name; 4 private int age; 5 6 //对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问 7 public int getAge(){ 8 return age; 9 } 10 11 public String getName(){ 12 return name; 13 } 14 //采用 this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。 15 public void setAge(int age){ 16 this.age = age; 17 } 18 19 public void setName(String name){ 20 this.name = name; 21 } 22 }