Java学习Day9-面向对象的特性,接口

继承的延续

指针可以指向对象,前提条件是:

在没有继承之前

        指针的数据类型与对象的数据类型必须一样

在有了继承之后

        指针的数据类型可以与对象的数据类型不一样

        如果存在继承关系,那么父类类型的指针可以指向子类类型的对象

        Object类的指针可以指向任意数据类型的对象

        这种将子类对象赋给父类指针的语法称为“向上转型”,隐式的

                继承是向上转型的前提

                向上转型是多态的前提

                向下转型的副作用是:指针无法访问下级对象中的成员

        “向下转型”需要显式的强制转换,通常伴随着instanceof做类型判断

                指针向下转型为下级类型,就又可以访问下级对象中的成员了

        如果使用了向上转型实现了多态指针,在用指针操作对象的时候又不想做“向下转型”,可以使用方法重写来实现 

        思考:Animal类型的指针为什么不能调用show()方法,因为Animal类中没有show()方法

                 1、在父类Animal中添加一个show()方法

                        animalArray[i].show();此时animalArray[i]不需要向下转型也可以调用show()方法

                2、在子类中出现与父类中的同名方法的时候,就存在方法重写的关系

                        那么此时当使用父类类型指针调用方法的时候,如果当前子类中有存在满足重写关系的方法的时候,会自动向下去调用子类重写的方法

abstract 关键字:抽象

        可以修饰成员方法和类

        成员方法被abstract修饰后,称为抽象方法/虚方法,没有()方法体

        类被abstract修饰后,称为抽象类,不可以被实例化

        抽象方法必须出现在抽象类中,而抽象类中不一定必须有抽象方法

        如:Animal类被abstract修饰,称为抽象类

        Animal animal = new Animal() //报错,抽象类不可用实例化

 

 如何快速生成show()方法

 

        抽象类天生就是父类,天生就是被子类继承的

        子类继承父类的时候,如果父类中有抽象方法的话子类必须要重写,除非把子类也变为抽象类,让子类的子类去重写方法

        子类继承抽象类的时候,必须强制重写父类中的抽象方法

        例如:Dog,Cat,Pig这三个子类继承Animal父类

        Dog dog = new Dog();//一定正确

        Cat cat  = new Cat();//一定正确

        Pig pig = new Pig();//一定正确

        Animal animal1 = new Dog();//如果有继承关系Dog extens Animal 就正确

        Animal animal2 = new Cat();//如果有继承关系Cat extens Animal 就正确

        Animal animal3 = new Pig();//如果有继承关系Pig extens Animal 就正确

 向上转型副作用(成员变量、成员方法)测试

 

 我们会发现调用不了子类本身的成员方法,可以推出向上转型的时候子类的成员方法、成员变量丢失了

向下转型实例

public class Demo {
    static Animal[] animalArray = new Animal[10];
    static {
        Dog dog = new Dog();    //对象赋给指针,数据类型要兼容
        dog.setNickName("旺财");
        dog.setStrain("金毛");
        animalArray[0] = dog;   //指针赋给指针,数据类型要兼容        向上转型
        Cat cat = new Cat();
        cat.setNickName("加菲猫");
        cat.setColor("红色");
        animalArray[1] = cat;                                       //向上转型
        Pig pig = new Pig();
        pig.setNickName("二师兄");
        pig.setArea("天庭");
        animalArray[2] = pig;                                       //向上转型

    }

    public static void main(String[] args) {
        //animalArray[0]是animalArray类型的指针,无法访问到子类的方法
        //animalArray[0].show()
        //animalArray[0]指针向下转型为Dog类型
//        Dog dog = (Dog)animalArray[1];  //运行时出现ClassCastException类型转换异常,语法没错,但运行时出错,因为animalArray[1]是Cat类型的
//        Dog dog = (Dog)animalArray[0];
//        dog.show();
        for (int i = 0; i < animalArray.length; i++) {
            if (animalArray[i] == null) {       //减少遍历次数,增加性能
                break;
            }
            //在向下转型的时候通常会伴随类型判断
            //类型判断的运算符是一个关键字    instanceof
            //instanceof语法:指针 instanceof  类型
            //instanceof的返回值是boolean类型
            if (animalArray[i] instanceof Dog) {
                Dog dog = (Dog)animalArray[i];
                dog.show();
                //((Dog) animalArray[i]).show();
            } else if (animalArray[i] instanceof Cat) {
                ((Cat) animalArray[i]).show();
            } else if (animalArray[i] instanceof Pig) {
                ((Pig) animalArray[i]).show();
                //(Pig) animalArray[i].show();如果没有括号,先执行animalArray[i].show();然后执行(Pig)向下转型,转型的是show()
            }
        }


//        System.out.println(animalArray[0].getNickName());
//        System.out.println(animalArray[0].getStrain());   没有向下转型,无法编译,因为找不到子类中的方法
//        System.out.println(animalArray[1].getNickName());
//        System.out.println(animalArray[1].getColor());    没有向下转型,无法编译,因为找不到子类中的方法
//        System.out.println(animalArray[2].getNickName());
//        System.out.println(animalArray[2].getArea());     没有向下转型,无法编译,因为找不到子类中的方法
    }
}

多态 - 面向对象的第三大特性

与多态相反的是单态

多态的指针(指针的类型是抽象的)

        Animal animal

单态的指针(指针的类型是具体的)

        Dog dog

        Cat cat

        Pig pig

多态的数组,数组元素是指针,指针多态

单态的数组,数组元素是指针,指针单态

面向对象整理

面向过程和面向对象的区别

面向过程编程思想不考虑封装、继承、多态这些事情,直接定义数据为静态变量,用静态函数去操作数据。面向过程编程,代码不具有可复用性和可扩展性

面向对象编程思想需要先抽象出实体的结构,并用类进行封装,用成员变量表达实体的属性,用成员方法封装对实体属性的操作,提供构造方法构造对象,基于对象编程。面向对象编程,代码具有可复用性和可扩展性

举例:实现汽车租凭系统

        面向过程的思想:

                定义多个静态数组,存储汽车各项数据,直接定义静态函数实现各种业务的过程

        面向对象的思想:

                先抽象出汽车实体的结构,并使用汽车类进行封装,然后创建汽车数组存储汽车实体的数据,再考虑业务功能的实现

面向对象的三大特性

  • 1、封装
  • 2、继承
  • 3、多态

第一特性:封装

 用成员变量来描述对象的属性,并用private进行私有化封装,不对外暴露对象的属性,防止外部对属性误操作

用成员方法来封装对属性的操作,并暴露给外部调用:典型的就是setter和getter,一个是提供给外部进行属性值的设置,一个是提供给外部读取属性的值

面向过程静态变量面向对象成员变量
静态方法成员方法
静态代码块构造方法

第二特性:继承

  1. 继承是Java中类与类之间的一种关系
  2. 继承的关键字是extends
  3. 发生继承的类称为子类,被继承的类称为父类
  4. Java不支持多继承,只支持单继承,但支持多级继承,一个类只能继承一个父类,但是一个父类可以有多个子类
  5. 如果一个类没有显式继承父类,则隐式继承Object类
  6. 子类可以继承父类的非私有(非private修饰)成员(包括成员变量和成员方法)
  7. 父类的构造方法子类不能继承,但可以用super()调用
  8. 父类的静态成员与继承无关
  9. 如果父类中有抽象方法,子类必须重写,除非子类也有抽象类,让子类的子类去重写(实现)

第三特性:多态

先有继承而后有多态,多态的反义词是单态

 1、指针的多态(数组的多态、参数的多态、返回值的多态归根到底都是指针的多态)

        如果指针是具体的子类类型,则指针是单态指针,只能指向具体的子类对象

        如果指针是抽象的父类类型,则指针是多态指针,可以指向任意的子类对象

2、方法的多态(1、基于重载实现        2、基于重写实现)

        重载是编译时多态的体现

        重写是运行时多态的体现

重载和重写的区别

重载和重写都是方法多态的体现

重载(overload)是编译时多态的体现

  1. 重载发生在同一个类中,Java允许一个同一个类中的多个方法同名存在,但必须要满足重载的要求
  2. 方法名相同,但方法的参数列表不同(可以是参数个数不同,可以是参数类型不同)
  3. 重载与面向对象无关,与面向过程也无关,静态方法、构造方法、成员方法都可以重载

重写(override)是运行时多态的体现

  1. 重写发生在子类与父类之间,子类重写父类的方法,其目的是:当使用父类类型的指针调用子类方法的时候,可以无需做向下转型
  2. 子类方法与父类方法同名
  3. 访问修饰符要大于等于父类方法
  4. 参数个数必须与父类一样,参数类型可以小于等于父类方法的参数类型
  5. 返回值类型可以小于等于父类方法的返回值类型

抽象类和抽象方法的关系

  1. 抽象类和抽象方法都需要使用abstract关键字修饰
  2. 抽象方法必须出现在抽象类中
  3. 抽象类中可以有抽象方法,也可以没有

 普通类和抽象类的区别

普通类可以实例化,也可以被继承

抽象类不可以实例化,只能被继承

实例化就是new 构造方法()创建对象

向上转型和向下转型的区别

向上转型

  1. 将子类对象/指针赋给父类指针的语法称为“向上转型”,隐式的
  2. 继承是向上转型的前提,向上转型的目的是为了实现多态的指针
  3. 向上转型的副作用:指针无法访问下级对象中的成员(除非发生了重写)

 向下转型

  1. 将父类类型指针赋给子类类型指针的语法称为“向下转型”,需要显式的强制类型转换,通常伴随着instanceof做类型判断,否则可能会出现ClassCastException(类型转换异常)
  2. 指针向下转型为子类类型,就可以访问子类中特有的成员了(非重写的成员方法)

 访问权限修饰符

修饰符当前类同包子类其他包
private私有的可见不可见不可见不可见

(default)

不写修饰符的意思

默认的可见可见不可见不可见
protected受保护的可见可见可见不可见
public公有的可见可见可见可见

private的特点:只有本类可见

(default)的特点:只有同包可见

protected的特点:子类可见

public的特点:任何地方都可见

接口

1、接口也是一种源代码文件

        定义类的关键字class

        定义接口的关键字interface

2、接口的出现让Java也能实现多继承,一个类只能继承一个父类,但是可以继承多个接口

        子类继承父类,关键字是extends

        子类继承/实现/扩展接口,关键字是implements

3、接口与抽象类进行比较

        相同点:

                1、都可以作为指针的类型,实现多态指针

                2、都不可以实例化

        不同点:

                1、抽象类用class定义,接口用interface定义

                2、抽象类用extends继承,接口用implement实现

                3、类只能单继承,接口可以多实现

                4、抽象类虽然不可以被实例化,但是抽象类可以有构造方法,接口不可以有构造方法

                5、抽象类可以有抽象方法,也可以有具体方法,接口只能有抽象方法,且接口中所有的方法默认是“public abstract ” 修饰的

                6、抽象类可以有成员变量,接口不能有成员变量,只能有静态常量

接口的使用思路

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值