面向对象的三大特征(封装、继承和多态)

面向对象所具有的三大特征封装、继承和多态,他们都有着重用的目的,为了让我们程序员更方便的书写代码阅读代码,不需要重复的书写相同或类似的代码块,从而产生了面向对象的三大特征,但三大特征的处理都有着解决代码重用的特性,还有着一些其他的用途,下面将分别详细介绍面向对象三大特性的使用思想,本文均个人理解,如有其他见解,请指正。

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();// 狗会看家

    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值