Java面向对象三大特征
Java面向对象的三大特征是封装、继承和多态,本文主要针对此三大特征作一个简单的概括和描述。
Java语言
Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。
面向对象与面向过程的区别
- 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了,例如我们常见的“C语言”、“Fortran语言”等。
- 面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为,例如“Java"、“C#”、“C++”等。
下面举几个简单的例子:
- 例子1(知乎上看的):
面向对象:狗(摇尾巴)
面向过程:摇(狗尾巴)- 例子2:
需求:我需要买一台电脑
面向对象:我请班长去帮我买,但是具体班长是怎么买的我并不关心。
面向过程:首先我在网上搜寻了很多电脑的信息,然后经过比较挑选罗列出自己心怡的几款电 脑,然后去坐车去电脑城,实物体验,最终买到自己需要的电脑。
特征一:封装
封装概述:
- 是面向对象三大特征之一,面向对象编程语言是对客观世界的模拟,客观事件中的成员变量都是隐藏在对象内部的,外界无法直接操作。
封装原则:
- 将将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问成员变量private,提供对应的getXxx()/setXxx()方法。
封装好处:
- 通过方法来控制成员变量的操作,提高了代码的安全性把代码用方法进行封装,提高了代码的复用性。
下面是一个标准学生类的示例:
/*
标准学生类
*/
class Student {
//成员变量私有化
private String name; //姓名
private String gender; //性别
private int age; //年龄
//无参构造
public Student() {}
//有参构造
public Student(String name,String gender,int age) {
this.name = name;
this.gender = gender;
this.age = age;
}
//每个属性对应的get/set方法用于操作属性
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
注意:
创建对象并为其成员变量赋值的两种方式
- 无参构造方法创建对象后使用setXxx()赋值
- 使用带参构造方法直接创建带有属性值的对象
特征二:继承
继承概述:
- 简单来说,继承就是在一个已有类的基础上派生出新类。子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
使用场景:
- 一个类想要拥有其他类的成员和方法;
- 多个类拥有相同的属性和方法时,可以抽取出相同的部分。
继承的好处跟弊端:
- 好处
- 提高了代码的复用性;
- 提高了代码的可维护性。
- 弊端
- 类与类之间产生了关系,削弱了子类的独立性,提高了类的耦合性,违背了代码编写低耦合高内聚的准则。
特点:
类的特点
- 只支持单继承,不支持多继承,但是可以支持多层继承;
注意:
- 只有满足"is a"规则关系的两个类才能继承;
- 父类中定义的方法必须是抽取所有成员共有的方法。
附:“is a”法则简单来讲就是,如果事物a能够继承事物b,一定满足“a is a b”;例如狗能继承动物,那么肯定的“狗 is a 动物”。
变量的特点
- 在子类方法中访问一个变量
1.子类局部范围找
2. 子类成员范围找
3. 父类成员范围找
4. 如果都没有就报错
注意:
- 子类不能继承父类中的私有成员,但是可以通过父类公共的get\set方法获取到;
- 子类不能够继承父类的构造方法,但是可以通过super关键字进行访问;
- 子类构造方法执行前,都会先执行父类的无参构造方法,建议写一个类的时候,永远手动给出无参的构造;
- super(…)必须出现在构造方法的第一条语句,如果没有会自动加上。
构造方法的特点
- 在有子父类继承关系的类中,创建子类的对象,调用子类的构造方法,如果子类的构造方法的第一行代码没有调用父类的构造方法,那么就会默认调用父类的无参构造;
- 我们可以使用super()在构造方法的第一行中调用父类的构造方法;
- 肯定会先执行父类的构造(子类会使用到父类的成员变量,所以父类要先进行初始化)。
方法重写
应用场景:
- 子类继承了父类的某些功能,但是这些功能不能够满足需求时需要在原来的方法上增加某些功能。
注意事项:
- 父类的私有方法(private修饰)不能被重写,因为子类都无法继承父类的私有成员;
- 子类方法的访问权限不能低于父类方法的访问权限。
下面是一个继承使用的示例:
//父类
class Phone{
//提取到的共同的属性和行为
String color;
int model;
public void callPhone() {
System.out.println("打电话");
}
}
//子类
class Iphone extends Phone{
// String color;
// int model;
String gui;
public void fangshui() {
System.out.println("防水");
}
public void callPhone() {
//方法重写,在父类方法的基础上增加了语音拨号的功能
System.out.println("语音拨号");
System.out.println("打电话");
}
}
特征三:多态
多态概述:
- JAVA类被jvm加载运行时根据调用该方法的对像实例的类型来决定选择调用哪个方法则被称为运行时多态。也叫动态绑定:是指在执行期间判断所引用对象实例的实际类型,根据其实际的类型调用其相应的方法。
使用前提:
- 子父类的继承关系
- 有方法的重写
- 父类引用指向子类对象(向下转型)
成员特点:
- 成员变量编译时看左边,执行时也看左边;
- 成员方法编译时看左边,执行时看右边(因为方法存在重写,有动态绑定);
- 静态方法编译时看左边,执行时也看左边。
好处跟弊端:
- 好处:提高了程序的扩展性跟可维护性;
- 弊端:不能够使用子类的特有功能。
向上转型跟向下转型:
- 向上转型(自动转型):小的转大的(类似多态);
- 向下转型(强制转型):大的转小的。
下面是一个多态使用实例:
父类(动物)
class Animal{
int num = 10;
static int age = 20;
//定义了动物的吃饭行为
public void eat(){
System.out.println("吃饭");
}
//定义了动物的睡觉行为
public void sleep(){
System.out.println("睡觉");
}
}
子类一(猫):
class Cat extends Animal{
int num = 80;
static int age = 90;
//定义了猫吃饭的具体行为
public void eat(){
System.out.println("猫吃鱼~");
}
public void sleep(){
System.out.println("猫在睡觉~");
}
}
子类二(狗):
class Dog extends Animal{
int num = 60;
static int age = 70;
//定义了狗吃饭的具体行为
public void eat(){
System.out.println("狗啃骨头~");
}
public void sleep(){
System.out.println("狗在睡觉~");
}
}
测试类:
class TestDemo{
public static void main(String[] args){
Animal a = new Cat();
Animal b = new Dog();
a.eat();
b.eat();
a.sleep();
b.sleep();
System.out.println(a.num);
System.out.println(a.age);
System.out.println(a.num);
System.out.println(a.age);
}
}
根据上述多态的特点,想必大家已经知道了输出结果,没错,结果就是:
"猫吃鱼~" "狗啃骨头~" "猫在睡觉~" "狗在睡觉~" 10 20 10 20