面向对象(动态&抽象类)

目录

导读

        多态

        抽象类

1.1. 多态

        1.1.1. 多态实现原理

        1.1.2. 多态的优点

        1.1.3. 对象转型

                向上转型

                向下转型

        1.1.4. instanceof关键字

        1.1.5. 多态中的方法重写

        1.1.6 父子类出现同名成员

1.2. 抽象类

        1.2.1. 抽象类定义

        1.2.2. 抽象方法

                        抽象方法的特点

        1.2.3. 抽象类的继承

        1.2.4. 抽象类总结

                基本点总结:

                比较普通类与抽象类

                比较:final,abstract,static,private


导读

        多态

  • 生活中的多态, 是指的客观的事物在人脑中的主观体现。 例如, 在路上看到一只哈士奇, 你可以看做是哈士奇, 可以看做是狗, 也可以看做是动物。
  • 主观意识上的类别, 与客观存在的事物, 存在 is a 的关系的时候, 即形成了多态。
  • 在程序中, 一个类的引用指向另外一个类的对象, 从而产生多种形态。 当二者存在直接或者 间接的继承关系时, 父类引用指向子类的对象, 即形成多态。
  • 多态是面向对象三大特性之一,学好多态对我们学习java非常重要,记住继承是多态的前提,如果 类与类之间没有继承关系,也不会存在多态.

        抽象类

  • 程序, 是来描述现实世界, 解决现实问题的。
  • 例如, 我们在进行百度图片搜索的时候, 搜索的关键字是动物, 但是搜索的结果却都是的子类对象。
  • 在现实世界中, 存在的都是动物具体的子类对象, 并不存在动物对象。 所以Animal类不 应该被独立创建成对象。
  • 对于这样的场景, 我们可以将动物类, 设计为抽象类。 抽象类不能被实例化对象, 只是提 供了所有的子类共有的部分。

1.1. 多态

        1.1.1. 多态实现原理

  • 多态:在代码中的描述是用父类的引用指向子类的对象
父子关系:Student extends Person Person extends Object 
//直接父类的引用指向子类对象---多态 
Person person = new Student(); 
//Object不是Student的直接父类,但是是间接父类,这里也是多态 
Object o = new Student();
  • java程序运行分成两个阶段:编译,运行
  1. 编译阶段:从打开程序到执行运行之前---只能识别=前面的引用类型,不会识别=后面的对象
  2. 运行阶段:从运行开始---识别=后面对象,对象开始干活儿
例如:Person person = new Student(); 
编译阶段识别: person 是Person类的引用 
运行阶段识别:new出来的Student对象
  • 动态机制
  1. 类型:动态类型,动态绑定,动态加载
  2. 动态加载:我们在编译阶段不能确定具体的对象类型,只有到了运行阶段才能确定真正的干活儿 的对象.
  3. 多态就是典型的动态加载

        1.1.2. 多态的优点

  • 可以提高代码的扩展性,使用之前定义好的功能,后面直接拿来使用,不用再创建新的方法

        1.1.3. 对象转型

                向上转型

        对象由子类类型, 转型为父类类型, 即是向上转型

  • 向上转型是一个隐式转换,相当于自动类型转换, 一定会转型成功。
  • 向上转型后的对象, 只能访问父类中定义的成员。
  • 作用:实现多态
/*** @Description 向上转型 */ 
class Test { 
    public static void main(String[] args) { 
    // 1. 实例化一个子类对象 
    Dog dog = new Dog(); 
    // 2. 转成父类类型 
    Animal animal = dog; 
    // 此时, 这个animal引用只能访问父类中的成员 
    animal.name = "animal"; 
    animal.age = 10; 
    animal.furColor = "white"; // 这里是有问题的, 访问不到 
    } 
}
class Animal { 
    String name; int age; 
}
class Dog extends Animal { 
    String furColor; 
}

                向下转型

  • 对象由父类类型, 转型为子类类型, 即是向下转型。
  • 向下转型是一个显式转换,相当于强制类型转换, 有可能转型失败.
  • 向下转型后的对象, 将可以访问子类中独有的成员。
/*** @Description 向下转型 */
class Test { 
    public static void main(String[] args) { 
    // 1. 实例化一个子类对象 
    Dog dog = new Dog(); 
    // 2. 转成父类类型 
    Animal animal = dog; 
    // 3. 转成子类类型 
    Dog sub = (Dog)animal;
    //注意: //1.这不是父类的引用指向子类的对象,不是向上转型.这是使用子类的引用指向父 类的对象是错误的.
    Animal animal1 = new Animal(); 
    Dog dog2 = (Dog)animal1; 
    }
}
class Animal { 
    String name; 
    int age; 
    }
class Dog extends Animal { 
    String furColor; 
}

        1.1.4. instanceof关键字

向下转型, 存在失败的可能性。 如果引用实际指向的对象, 不是要转型的类型, 此时强制 转换, 会出现 ClassCastException 异常。 所以, 在向下转型之前, 最好使用 instanceof 关键字进行类型检查。
  • instanceof:是一个运算符
  • 构成: 对象 instanceof 类或类的子类
  • 原理说明:确定当前的对象是否是后面的类或者子类的对象,是返回true,不是false
  • 作用:进行容错处理,增加用户体验
public class Demo7 { 
    public static void main(String[] args) { 
    Person person = new Student(); 
    person = new Teacher();
    //发生错误代码 
    //当用Student类型的引用指向Teacher类型的对象时,因为Student和Teacher没 有关系. 
    //所以发生ClasscastException:类型转换异常,一旦发生了异常,程序会立刻停止 
    // Student student = (Student)person; // student.run(); 
    //解决问题:容错处理 
    //如果person对应的对象不是Student或者Student的子类的对象,这里返回false
    if (person instanceof Student){ 
        Student student = (Student)person; 
        student.run(); 
    }else { 
        System.out.println("提供的不是Student类型的对象"); 
        //类型转换异常. 
        Exception exception = new ClassCastException("发生了类型转换异 常");                 
        exception.printStackTrace(); 
    }
}
class Person{ 
    String name; 
    public void show(){ System.out.println("show"); 
    } 
}
class Student extends Person{
    int age; 
    public void run(){ System.out.println("run"); }
}
class Teacher extends Person{ 
    int weight; 
    @Override 
    public void show() { System.out.println("Teacher-show"); } 
}

        1.1.5. 多态中的方法重写

当向上转型后的对象, 调用父类中的方法。 如果这个方法已经被子类重写了, 此时调用的就 是子类的重写实现!
        
class Test { 
    public static void main(String[] args) { 
    // 1. 实例化一个子类对象, 并向上转型 
    Animal animal = new Dog(); 
    // 2. 调用父类方法 
    animal.bark(); 
    // 因为在子类中已经重写过这个方法了, 此时的输出结果是 Won~
    } 
}
class Animal { 
    public void bark() { System.out.println("Animal Bark~");}
}
class Dog extends Animal { 
    @Override 
    public void bark() { System.out.println("Won~"); } 
}

        1.1.6 父子类出现同名成员

  • 继承下的调用规则
  1. 成员变量:调用子类的
  2. 成员方法:调用子类的,子类没有再去调用父类的.
  • 多态下的调用规则:
  1.  成员变量:编译的时候能不能访问看父类,运行的时候也看父类
  2. 成员方法:编译的时候能不能访问看父类,运行的时候看子类
  3.  静态成员方法:编译运行都看父类

1.2. 抽象类

        1.2.1. 抽象类定义

        在继承中, 提取父类方法的时候 , 每个子类都有自己具体的方法实现 , 父类不能决定他们各自的实 现方法, 所以父类干脆就不管了 , 在父类中只写方法的声明 ( 负责制定一个规则 ), 将方法的实现交 给子类. 在类中只有方法声明的方法叫抽象方法 , 拥有抽象方法的类叫抽象类
  • abstract:抽象的
  • 声明:不写函数体的函数,可以叫声明
  • abstract修饰方法:抽象方法
  • abstract修饰类:抽象类
  • 抽象类的功能:1.可以节省代码 2.可以制定一批规则

        1.2.2. 抽象方法

                        抽象方法的特点

  • 抽象方法只有方法的声明, 没有实现。
  • 抽象方法只能定义在抽象类中
/***  @Description 抽象类 */ 
abstract class Animal { 
    // 抽象方法,只有方法的声明, 没有方法的实现 
    // 只能定义在抽象类中 
    public abstract void bark(); 
}

        1.2.3. 抽象类的继承

        抽象方法有一个特点, 就是只能定义在抽象类中。 如果一个非抽象子类继承自一个抽象父 类, 此时, 可以继承到抽象父类中的抽象方法。 那么这个时候, 抽象方法就存在于一个非抽象的子类中了。 此时会有问题。
        所以, 非抽象的子类, 在继承自一个抽象父类的时候, 必须重写实现抽象父类中所有的抽象 方法或者将自己也变成抽象类
  • 注意:抽象类不能直接创建对象,可以通过子类间接的创建对象
public class Demo8 {
    public static void main(String[] args) { 
    //抽象类不能直接创建对象,可以通过子类间接的创建对象. 
    // Animal animal = new Animal(); 
    } 
}
abstract class Animal { 
    // 抽象方法,只有方法的声明,没有方法的实现(前面必须添加abstract关键字) 
    // 只能定义在抽象类中 
    public abstract void bark(); 
}
//处理方法一:重写父类抽象方法 
class Dog extends Animal { 
    @Override 
    public void bark() { System.out.println("won~"); } 
}
//处理方法二:将自己变成抽象方法 
abstract class Dog extends Animal { }

        1.2.4. 抽象类总结

                基本点总结:

  • 抽象类不一定有抽象方法,但是有抽象方法的一定是抽象类.
  • 继承了抽象类的子类一定要实现抽象方法,如果不实现就只能将自己也变成抽象的.
  • 抽象类不能直接创建对象,必须通过子类实现,所以抽象类一定有子类

                比较普通类与抽象类

  • 普通类可以直接创建对象
  • 抽象类可以有抽象方法

                比较:final,abstract,static,private

  • 三个都是不能与abstract同时存在的关键字
  • final:final修饰的类不能有子类,方法不能重写,但是abstract必须有子类,必须重写
  • static:修饰的方法可以通过类名调用,abstract必须通过子类实现
  • private:修饰的方法不能重写,abstract必须重写

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值