面向对象所具有的三大特征封装、继承和多态,他们都有着重用的目的,为了让我们程序员更方便的书写代码阅读代码,不需要重复的书写相同或类似的代码块,从而产生了面向对象的三大特征,但三大特征的处理都有着解决代码重用的特性,还有着一些其他的用途,下面将分别详细介绍面向对象三大特性的使用思想,本文均个人理解,如有其他见解,请指正。
1、封装
封装是一种将对象内部的细节进行隐藏,外界不必知道他具体是怎么实现的,只要提供对应的接口,让外界使用他的思想。在现实中就如同我们的房子,不是透明的,不想让外界知道我们的房子里面具体有些什么,对外就只需要知道他可以住宿,知道门在哪就行,对于房子里面的具体有些什么东西外界就不需要知道了,这就是我们的封装思想。
1.1 概述
是面向对象编程语言对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界是无法直接操作的
1.2 封装的好处
提高了代码的安全性:被封装的成员变量不能被外界随意修改,需要使用对应的方法才能改变
提高了代码的复用性:当需要实现多次相同的功能时,可以将代码封装起来,需要使用时只需要调用方法即可,不需要在写一遍相同的代码
1.3 关键字private
pricate是使用封装技术重要的一部分,pricate是一个权限修饰符其意为私有的,即将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问,成员变量private,提供对应的getXxx()/setXxx()方法
针对private修饰的成员变量,如果需要被其他类使用,提供相应的操作
提供“get变量名()”方法,用于获取成员变量的值,方法用public修饰
提供“set变量名(参数)”方法,用于设置成员变量的值,方法用public修饰
例如:定义一个学生类,其中他的年龄外界不能随意更改,将年龄设为私有的(private),提供set方法进行对成员变量进行赋值,赋值前可以先判断这个值是否合理,代码如下:
class Student {
//成员变量
String name;
private int age;
//提供get/set方法
public void setAge(int a) {
if(a<0 || a>120) {
System.out.println("你给的年龄有误");
} else {
age = a;
}
}
public int getAge() {
return age;
}
}
1.4 关键字this
this 修饰的变量用于指代成员变量,其主要作用是(区分局部变量和成员变量的重名问题)
如上述代码中对年龄进行更改时,将传进来的参数a赋值给了成员变量age,年龄我们通常使用age来表示,若传进来的参数名称也是age,参数与成员变量同名,在成员方法中的age指的就是传进来的参数,若需要使用成员变量age就需要使用this关键字。
修改set方法代码如下:
public void setAge(int age) {
if(age<0 || age>120) {
System.out.println("你给的年龄有误");
} else {
this.age = age;
}
}
2、继承
为了提高代码的复用性,对具有相同属性和方法的对象创建出共同的类,而为了提高类中代码的复用性,便有了继承,通过继承可以让多个类具有相同的方法,其中被继承的类被称为父类,继承的类被称为子类,在使用子类时可以调用其父类非私有的方法,提高了代码的复用性。
继承可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及追加属性和方法
2.1 继承的格式
继承通过关键字extends实现
格式:
class 子类 extends 父类 { }
注意:类不支持多继承如:A extend B,C
但是支持多重继承:A extend B;B extend C
2.2 继承的好处与弊端
好处:
提高了代码的复用性(多个类相同的成员可以放到同一个类中)
提高了代码的维护性(如果方法的代码需要修改,修改一处即可)
弊端:
通过继承增加了类与类之间的耦合性,当父类进行更改时,子类也会发生改变。所以在使用继承时一定要考虑清楚他们之间的联系,有没有 “谁是谁的一种” 的这种关系
例如:狗是动物的一种,猫也是动物的一种,所以我们定义狗这个类和猫这个类时可以先定义出动物类,他们就可以进行继承动物类。
2.3 继承中变量的访问特点
在子类方法中访问一个变量,采用的是就近原则。
1. 子类局部范围内找(局部变量)
2. 子类成员范围内找(成员变量)
3. 父类成员范围内找(父类的成员变量)
4. 如果父类成员范围内也找不到就报错(不考虑父类的父类)
2.4 super关键字
与this关键字一样都是对变量或方法重名时,对指代的对象引用进行标识,而this用于表示指代本类的对象引用,super用于指代父类的对象引用。
例如:
public class Animal {
String name;
int age;
public Animal() {// 初始化
this.name = "动物";
}
}
public class Dog extends Animal{
private String name;
private int age;
public void show1(){
System.out.println(name);
}
public void show2(){
System.out.println(super.name);
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.show1();// null
dog.show2();// 动物
}
}
在Dog类中定义了两个方法,都是对name进行输出,其中show2类加了关键字super,则指代输出父类的name,因为创建的dog对象没有进行初始化,所以使用show1输出的是String类型的默认值null,而show2输出的是Dog类的父类Animal初始化好的名字:动物
2.5 继承中的构造方法的访问特点
在继承中访问子类的构造方法默认第一句为super();所以在初始化子类之前,会先完成父类的初始化。
如果父类没有无参构造方法,只有有参构造方法,可以使用super关键字去显示的调用父类的带参构造方法,或自己在父类添加一个无参构造方法,推荐使用在父类添加无参构造方法。
2.6 方法的重写
在子类继承父类时,子类可能不想使用父类的某些方法,想将父类的方法进行特殊化,但是又需要使用这个方法名称且方法的参数列表也是一致时,便需要方法的重写,对重写的方法通常加上Override注解
例如:Dog类重写了Animal类中的show方法
public class Animal {
String name;
int age;
public void show(){
System.out.println("动物");
}
}
public class Dog extends Animal{
private String name;
private int age;
@Override
public void show() {
System.out.println("狗");
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.show();// 狗
}
}
使用重写时需要注意:
1.私有方法不能被重写(父类的私有成员子类是不能继承的)
2.子类的访问权限不能更低(public > 默认 > private)
3、多态
多态是指同一个对象,在不同时刻表现出来的不同形态
3.1 多态的前提
1. 要有继承或实现关系
2. 要有方法的重写
3. 要有父类引用指向子类对象
3.2 多态的访问特点
成员变量:编译看父类,运行看父类
成员方法:编译看父类,运行看子类
public class Animal {
String name;
int age = 20;
public void show(){
System.out.println("动物");
}
}
public class Dog extends Animal{
private String name;
private int age = 10;
@Override
public void show() {
System.out.println("狗");
}
public void lookHome(){
System.out.println("狗会看家");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();
System.out.println(animal.age);//输出20 成员变量:编译看父类,运行看父类
animal.show();// 输出狗 成员方法:编译看父类,运行看子类
// animal.lookHome; // 不能使用子类特有的方法
}
}
如上代码中使用了多态进行创建对象animal 在使用他的成员变量时和他的类型Animal一样,使用他的方法时,和他的子类Dog一样,且不能使用Dog类特有的方法,只能使用子类重写了父类的方法。
3.3 多态的好处于弊端
好处:提高了程序的扩展性。在定义方法时,可以使用父类型作为参数,在使用的时候,在根据使用具体的子类型参与操作
弊端:在使用时不能使用子类的特有成员
3.4 多态中的转型
向上转型:父类引用指向子类对象就是向上转型(如:Animal animal = new Dog())
向下转型:子类引用指向父类对象(如 Dog dog = (dog) new Animal)
如上代码若需要使用子类的成员变量和非重写的方法时,可以将代码更改为:
public class Animal {
String name;
int age = 20;
public void show(){
System.out.println("动物");
}
}
public class Dog extends Animal{
private String name;
private int age = 10;
@Override
public void show() {
System.out.println("狗");
}
public void lookHome(){
System.out.println("狗会看家");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();
System.out.println(animal.age);// 成员变量:编译看父类,运行看父类
animal.show();// 成员方法:编译看父类,运行看子类
// animal.lookHome; // 不能使用子类特有的方法
Dog dog = (Dog)animal;// 向下转型
System.out.println(dog.age);// 10
dog.show();// 狗
dog.lookHome();// 狗会看家
}
}