Java修炼之凡界篇 筑基期 第06卷 面向对象 第04话 封装、继承和多态

本文详细介绍了面向对象编程的三大特性——封装、继承和多态。封装通过信息隐藏和get/set方法保护数据,提高安全性。继承允许子类扩展父类,实现代码复用,Java中单继承并默认继承Object类。多态则表现为一个对象根据其引用类型可以表现出多种行为方式。此外,还讨论了super关键字、重写、类型转换以及instanceof运算符的使用。
摘要由CSDN通过智能技术生成

封装、继承和多态

封装

  • 程序设计追求“高内聚、低耦合”

  • 高内聚:类的内部数据操作细节自己完成,不允许外部干涉

  • 低耦合:仅暴露少量的方法供外部使用

  • 封装即信息隐藏,通常在开发过程中,应禁止直接访问一个对象中数据的实际表示,而应该通过操作接口来访问,称为信息隐藏

  • 属性私有,提供操作这些属性的方法(get/set方法)

  • 封装能够提高程序的安全性,保护数据;隐藏程序代码的实现细节;统一接口;提高系统可维护性

  • 程序案例:

    public class Application {
    
        public static void main(String[] args) {
            Person person = new Person();
            person.setPersonName("王小二");
    
            System.out.println(person.getPersonName());
        }
    }
    
    public class Person {
    
        /** 属性私有,只能是当前类使用 */
        /** 人员姓名 */
        private String personName;
    
        /** 人员年龄 */
        private int personAge;
    
        /** 人员性别 */
        private char personSex;
    
        /** 获取人员姓名属性值方法 */
        public String getPersonName() {
            return personName;
        }
        /** 给人员姓名属性赋值方法 */
        public void setPersonName(String personName) {
            this.personName = personName;
        }
    
        public int getPersonAge() {
            return personAge;
        }
    
        public void setPersonAge(int personAge) {
            this.personAge = personAge;
        }
    
        public char getPersonSex() {
            return personSex;
        }
    
        public void setPersonSex(char personSex) {
            this.personSex = personSex;
        }
    }
    

继承

  • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模

  • Java 中使用 extends 关键字来表示继承,extends 意为“扩展”,子类是父类的扩展

  • Java 中类只有单继承,没有多继承

  • 继承是类和类之间的一种关系(类和类之间的关系还有依赖、组合、聚合等)

  • 继承关系的两个类,一个为子类(派生类),一个为父类(基类),子类继承父类,使用关键字 extends 来表示

  • 子类和父类之间,从某种意义上来讲应该是具有“ is a ”的关系

  • Java 中所有的类,都默认直接或间接继承 Object 类(上帝类)

  • 子类继承了父类,则子类就拥有了所有父类的方法和属性(被 private 修饰的方法或属性除外,私有的属性和方法不能被继承)

  • IDEA 中可以通过Ctrl + h 来查看类的继承关系

  • super 关键字代表子类的父类对象,可以理解为指向自身父类对象的一个指针,this 关键字代表自身对象,可以理解为指向对象本身的指针

  • 在子类中使用 super 关键字调用父类的构造方法,必须在子类构造方法的第一个

  • super 调用只能出现在子类的方法或构造方法中

  • super 和 this 不能同时调用构造方法

  • this() 自身类的构造方法super() 父类的构造方法

  • 程序案例:

    public class Application {
    
        public static void main(String[] args) {
            Man man = new Man();
        }
    }
    
    public class People {
    
        public String name;
    
        private String money;
    
        public People() {
            System.out.println("这是人类!!!!!");
        }
    
        public void eat() {
            System.out.println("吃东西!!!!!");
        }
    }
    
    public class Man extends People {
    
        public String manAge;
    
        public Man() {
            // 子类构造方法中会隐式的加载父类构造方法super()
            // super();
            super.eat();
            // 子类不能继承父类私有的方法和属性
            super.name = "王大";
            System.out.println(super.name);
            System.out.println("这是男人!!!!!");
        }
    
        public void play() {
            System.out.println("男人正在玩!!!!!");
        }
    
    }
    
    public class Woman extends People {
    
        public long womanHair;
    
        public Woman() {
            super.eat();
            System.out.println("这是女人!!!!!");
        }
    
        public void longHair() {
            System.out.println("女人有长头发!!!!!");
        }
    }
    // --------------------------------------
    // 控制栏输出打印:
    /**
    这是人类!!!!!
    吃东西!!!!!
    王大
    这是男人!!!!!
     */
    

重写

  • 重写针对的都是方法,和属性无关,且需要有继承关系

  • 方法名称必须相同,参数列表必须相同,方法体可以不同,修饰符范围可以扩大,但不可以缩小:public > protected > default > private

  • 静态方法不可以重写父类方法,创建子类对象使用父类接收时,调用的是父类的静态方法

  • 非静态方法可以重写父类方法,创建子类对象使用父类接收时,调用的是子类的非静态方法

  • 程序案例:

    public class Application {
    
        public static void main(String[] args) {
            Man man1 = new Man();
            // 静态方法
            man1.reWrite(); // 输出 这是子类重写方法!!!
            // 非静态方法
            man1.write(); // 输出 这是子类写方法!!!
    
            People man2 = new Man();
            // 静态方法
            man2.reWrite(); // 输出 这是父类重写方法!!!
            // 非静态方法
            man2.write(); // 输出 这是子类写方法!!!
        }
    }
    
    public class Man extends People {
    
        public String manAge;
    
        public Man() {
        }
    
        public static void reWrite(){
            System.out.println("这是子类重写方法!!!");
        }
    
        public void write(){
            System.out.println("这是子类写方法!!!");
        }
    
    }
    

多态

  • 同一方法可以根据发送对象的不同而采用多种不同的行为方式

  • 一个对象的实际类型是确定的,但是可以指向对象的引用类型有很多(父类或有关系的类)

  • 多态存在的条件1:类之间存在继承关系

  • 多态存在的条件2:子类需要重写父类方法(static 修饰的方法(属于类不属于实例)、final 修饰的方法和 private 修饰的方法不能被重写

  • 多态存在的条件3:父类引用指向子类对象

  • 多态是方法的多态,属性没有多态性

  • 程序案例:

    public class Application {
    
        public static void main(String[] args) {
            // 一个对象的实际类型是确定的
            // new Student();
            // new Person();
    
            // 但是可以指向对象的引用类型有很多:父类的引用指向子类
            Student student1 = new Student();
            Person student2 = new Student();
            Object student3 = new Student();
    
            // 当子类没有run方法时,子类对象直接调用父类 run 方法,
            // 子类重写了父类 run 方法时,子类对象调用自身的 run 方法(尽管对象是被父类引用,也会走子类 run 方法)
            student1.run();// 输出 Son-run
            student2.run();// 输出 Son-run
    
            // 父类引用不能调用子类的方法
            // 对象可以执行那些方法,主要看对象左边的类型,和右边关系不大
            // student2.play(); // 程序报错不能编译
            ((Student)student2).play(); // 这样强制转换是可以的
            // Student 类(子类)能调用的方法都是自己的或者继承自父类的方法
            // Person 类(父类)能指向子类,但是不能调用子类的方法
            student1.play();
    
        }
    }
    
    public class Person {
    
        public void run(){
            System.out.println("Father-run");
        }
    }
    
    public class Student extends Person {
    
        @Override
        public void run(){
            System.out.println("Son-run");
        }
    
        public void play(){
            System.out.println("Son-play");
        }
    
    }
    

instanceof

  • 左边的对象是否是它右边的类的实例,返回 boolean 的数据类型

  • 类型转换存在条件1:父类引用指向子类的对象

  • 类型转换存在条件2:把子类转换为父类,向上转型,把父类转换为子类,向下转型(强制转换),会丢失子类自己的一些方法

  • 对象类型转换的好处,方便方法调用,减少重复代码,使得程序更简洁

  • 程序案例:

    public class Application {
    
        public static void main(String[] args) {
            // Object > String
            // Object > Person > Teacher
            // Object > String > Student
    
            System.out.println("=======Object=======");
            Object studentObj = new Student();
    
            System.out.println(studentObj instanceof Student); // 输出 true
            System.out.println(studentObj instanceof Person); // 输出 true
            System.out.println(studentObj instanceof Object); // 输出 true
            System.out.println(studentObj instanceof Teacher); // 输出 false
            System.out.println(studentObj instanceof String); // 输出 false
    
            System.out.println("=======Person=======");
            Person studentP = new Student();
    
            System.out.println(studentP instanceof Student); // 输出 true
            System.out.println(studentP instanceof Person); // 输出 true
            System.out.println(studentP instanceof Object); // 输出 true
            System.out.println(studentP instanceof Teacher); // 输出 false
            // System.out.println(studentP instanceof String); // 编译报错
    
            System.out.println("=======Student=======");
            Student Student = new Student();
    
            System.out.println(Student instanceof Student); // 输出 true
            System.out.println(Student instanceof Person); // 输出 true
            System.out.println(Student instanceof Object); // 输出 true
            // System.out.println(Student instanceof Teacher); // 编译报错
            // System.out.println(Student instanceof String); // 编译报错
            // 编译是否报错
            // 取决于 instanceof 左右两边类对象是否存在父与子的关系,存在编译成功,不存在编译报错
    
            System.out.println("=======类型转换=======");
            // 子类可以直接转换为父类,但是转换后的对象不能调用子类自己的方法
            Person sp = new Student();
            // sp.studentRun(); // 编译报错
    
            // 父类转换为子类,需要强制转换,但是会丢失子类自己本来的一些方法
            ((Student)sp).studentRun(); // 输出 studentRun
            Student student = new Student();
            student.studentRun(); // 输出 studentRun
            Person ps = student;
            // ps.studentRun(); // 编译报错
            
        }
    }
    
    public class Person {
    
        public void fatherRun(){
            System.out.println("fatherRun");
        }
    }
    
    public class Teacher extends Person{
    
        public void teacherRun(){
            System.out.println("teacherRun");
        }
    }
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莫在问

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值