面向对象-多态,封装,继承

面向对象


  1. 什么是对象? 什么是类?

  • 对象:软件中真是存在的单个的个体/东西

  • 类: 代表一类个体; 类是对象的模子,对象是类的具体的实例, 可以将类理解为 类别/模子/图纸

  • 类中可以包含:

  • 对象的属性/特征/数据-----------成员变量

  • 对象的行为/动作/功能-----------方法

  • 一个类可以创建多个对象

  1. 关键字

  • this: 指代当前对象(即指代调用者), 哪个对象调方法它指的就是哪个对象

  • 只能用在方法的里面, 方法中访问成员变量之前默认有一个this.

  • this的用法:

this.成员变量名----------------------------------访问成员变量(经常用)
当成员变量与局部变量同名时, 若想访问成员变量, 则不能省略this. ;否则以就近原则访问
this.方法名()--------------------------------------调用方法(一般不用)
this()------------------------------------------------调用构造方法(一般不用)
  • super: 指代当前对象的超类对象

  • super.成员变量名----------------------访问超类的成员变量

当超类成员变量和派生类成员变量同名时,super指超类的, this指派生类的
若没有同名现象,写super和this是一样的
  1. 构造方法: 空参构造/有参构造

  • 作用: 给成员变量赋值初始化

  • 语法:与类同名, 没有返回值类型(连void都没有)

  • 调用:在创建(new)对象时被自动调用

  • 若自己不写构造方法,则编译器默认提供一个无参构造方法,若自己写了构造方法,则不再默认提供

  • 构造方法可以重载, 即空参/有参构造

public class Car {
    String brand; //品牌
    String color; //颜色
    double price; //价格
    Car(){
    }
    Car(String brand,String color,double price){
    this.brand=brand;
    this.color=color;
    this.price=price;
    }
}
  1. 继承:

  • 作用: 复用代码

  • 通过extends 实现继承

  • 超类/父类: 共有的属性和行为

派生类/子类:特有的属性和行为

  • 派生类可以访问:超类的+派生类的, 超类不能访问派生类的

  • 一个超类可以有多个派生类,一个派生类只能有一个超类------单一继承

  • 具有传递性

class Aoo{}
class Boo extends Aoo{}
class Coo extends Boo{}
  • java规定:构造派生类之前必须先构造超类

  • 在派生类的构造方法中若没有调用超类的构造方法,则默认super()调用超类的无参构造方法

  • 在派生类的构造方法中若自己调用了超类的构造方法,则不再默认提供

注意: super()调用超类构造方法, 必须位于派生类构造方法中的第一行
public class Person {
    String name;
    int age;
    String address;
    Person(String name,int age,String address){
    this.name=name;
    this.age=age;
    this.address=address;
    }
    void sayHi(){
    System.out.println("大家好,我叫"+name+",今年"+age+"岁了,家
    住"+address);
    }
}
public class Student extends Person{
    StringclassName;
    Student(Stringname,intage,Stringaddress,StringclassName){
    super(name,age,address); //传递的是name/age/address的值
    this.className=className;
    //super(name,age,address);// 错误编译, 必须放在第一位
    }
    voidstudy(){
    System.out.println(name+"正在学习...");
    }
}

  • 继承的是超类的成员变量和普通方法,不包括超类的构造方法,超类的构造方法是被派生类通过super()来调用的,而不是继承的

class Aoo{
    int a;
    Aoo (){
    }
    void show(){
    }
}
class Boo extends Aoo{
    继承了Aoo类的a+show(),并没有继承Aoo类的构造方法
}
  1. 抽象类, 抽象方法 : 均由abstract 修饰

  • 抽象方法: 只有方法的定义,没有具体的实现 (没有方法体), 连{}都没有

  • 抽象类:

  • 包含抽象方法的类必须是抽象类, 但不包含抽象方法的类也可以声明为抽象类

  • 抽象类不能被实例化(new对象)

  • 抽象类是需要被继承的, 派生类:

必须重写抽象类中的所有抽象方法--------------变不完整为完整
  • 抽象类的意义:

  • 封装共有的属性和行为-----------------------代码复用

  • 可以包含抽象方法, 目的是为所有派生类统一入口(方法名字统一), 强制必须重写

public abstract class Animal {
    String name;
    int age;
    Animal(String name,int age){
    this.name=name;
    this.age=age;
    }
    abstract void eat();//抽象方法
}
public class Dog extends Animal{
    Dog(String name,int age){
    super(name,age);
    }
    void eat(){//重写的抽象方法
    System.out.println(color+"色的"+age+"岁的狗狗"+name+"正在吃肯
    头...");
    }
}
  1. 接口: 由 interface 定义

  • 是一种引用数据类型

  • 只能包含抽象方法(常量 、默认方法、静态方法、私有方法)

  • 不能被实例化

  • 接口是需要被实现/继承的, 实现类/ 派生类: 必须重写接口中所有的抽象方法

  • 注意: 重写接口中的方法时,必须加 public

interface Inter{
    public abstract void show(); //完整的写法
    void show();
    // void show (){}  编译错误, 抽象方法不能有方法体
}
class Aoo implements Inter {
    public void show () {}
}
public class InterfaceDemo {
    public static void main(String[] args) {
        //Inter o = new Inter(); //编译错误,接口不能被实例化
    }
}
  • 一个类可以实现多个接口, 用逗号分隔. 若又继承又实现时, 应先继承后实现

  • 接口可以继承接口

  1. 引用类型数组: ----------与基本类型数组的区别

  • 区别1: 给引用类型数组的元素赋值时, 需要new个对象

  • 区别2: 访问引用类型数组的元素的属性/行为时, 需要打点访

  1. 多态:多种形态

  • 向上造型/自动类型转换:

  • 超类型的引用指向派生类的对象

父类 引用 = new 子类();
  • 能点出来什么, 看引用的类型

编译看左边, 执行看右边
编译时看父类中是否有该方法,如果有, 执行时直接去子类找到该重写的方法
  • 向下转型/强转类型转换, 成功的条件只有两种:

  • 引用所指向的对象, 就是该类型

  • 引用所指向的对象, 实现了该接口或继承了该类

强转时,如果类型不同,会报ClassCastException类型转换异常
因此在强转之前可以先通过 instanceof 来判断引用的对象是否是该类型
注意: instanceof 返回boolean结果, 为true 即为强转成功
若想访问的属性/行为在超类中没有,则需要强制类型转换
  1. 成员内部类

  • 若A类(Baby)只让B类(Mama)用,并且A类(Baby)还想访问B类(Mama)的成员时,可以设计成员内部类

class Mama{ //外部类
    String name;
    void create(){
        Baby b =new Baby(); //内部类对象通常在外部类中创建
    }
    class Baby{ //内部类
        void show(){
        System.out.println(name); //简写
        System.out.println(Mama.this.name); //完整写法,Mama.this指外部类对象
        //System.out.println(this.name); //编译错误,this指当前Baby对象
        }
    }
}
  1. 匿名内部类: 简化代码

  • 若想创建一个派生类的对象,并且对象只创建一次, 可以设计为匿名内部类

注意:匿名内部类中不能修改外面的局部变量的值
问: 内部类有独立的.class文件吗?
答: 有
public class TimerDemo {
    public static void main(String[] args) {
        //想要创建一个派生类的对象,并且这个对象只用一次,可以设计为匿名内部类
/**
        匿名内部类:
        例如:new TimerTask() {
                @Override
                public void run() {System.out.println("起床了,懒鬼...");}
                }
        1.实现了接口或继承了类 {@Override  public void run() {System.out.println("起床了,懒鬼...");} } 这个匿名类 继承了 TimerTask这个类
        2.创建了对象 new 关键字创建了这个对象
        3.重写了方法{@Override
                public void run() {System.out.println("起床了,懒鬼...");}
                }
*/
        Timer timer = new Timer();
        int interval=5000;
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("起床了,懒鬼...");
            }
        },interval,1000);
    }
}
  1. package和import

  • package: 声明包------避免类的命名冲突-----------包名所有字母都小写

  • 同包中的类不能同名,但不同包中的类可以同名

  • 类的全称: 包名.类名 包名常常有层次结构

  • import: 导入类

  • 同包中的类可以直接访问, 但是不同包中的类不能直接访问, 若想访问:

  • 先import导入类,在访问类----------建议

  • 类的全称---------------------------太繁琐

本节相关案例代码


//父类 动物类
public abstract class Animal {
    String name;
    int age ;
    String color;
    Animal(String name, int age , String color){
        this.name =name;
        this.age=age;
        this.color=color;
    }
    void drink(){
        System.out.println("名字为:"+name+",颜色为:"+color+"的它正在喝水...." +"它今年"+age+"岁了");
    }
    abstract void eat ();
}

//接口 
public interface Swim {
    void swim();
}

//子类 狗类
public class Dog extends Animal implements Swim{
    String type;
    Dog(String name,int age , String color , String type){
        super(name,age,color);
        this.type=type;
    }
    void eat(){
        System.out.println("名字为:"+name+",颜色为:"+color+"的"+type+"它正在吃骨头...." +"它今年"+age+"岁了");
    }
    public void swim(){
        System.out.println("名字为:"+name+",颜色为:"+color+"的"+type+"它正在练习狗刨...." +"它今年"+age+"岁了");
    }
    void lookHemo(){
        System.out.println("名字为:"+name+",颜色为:"+color+"的"+type+"它正在看家...." +"它今年"+age+"岁了");
    }
}
//子类 鱼类
public class Fish extends Animal implements Swim{
    String tpye ;
    Fish(String name,int age , String color , String type){
        super(name, age, color);
        this.tpye=type;
    }
    @Override
    void eat() {
        System.out.println("名字为:"+name+",颜色为:"+color+"的"+tpye+"它正在吃小虾米...." +"它今年"+age+"岁了");
    }
    @Override
    public void swim() {
        System.out.println("名字为:"+name+",颜色为:"+color+"的"+tpye+"它正在溪水...." +"它今年"+age+"岁了");
    }
}
//子类 鸡类
public class Chick extends Animal  {
    String tpye;
    Chick(String name, int age, String color, String type) {
        super(name, age, color);
        this.tpye = type;
    }
    @Override
    void eat() {
        System.out.println("名字为:" + name + ",颜色为:" + color + "的" + tpye + "它正在吃小米粒...." +"它今年" + age + "岁了");
    }
    void layEggs(){
        System.out.println("名字为:"+name+",颜色为:"+color+"的"+tpye+"它正在下蛋...." +"它今年"+age+"岁了");
    }
}
//多态演示
public class Master {
    void feed(Animal animals){
        animals.eat();
        animals.drink();
    }
}
//测试类
public class Test {
    public static void main(String[] args) {
        //1.将不同对象(狗,鱼,鸡)统一封装到一个数组(动物数组)中来访问,实现代码的复用
        Animal[]animals=new Animal[3];
        animals[0]=new Dog("巧克力",2,"黑白","狗狗");
        animals[1]=new Fish("棒棒糖",1,"彩色","鱼");
        animals[2]=new Chick("玉米棒",3,"黄色","小鸡");
        for (int i = 0; i < animals.length; i++) {
            //多态  编译看左边,运行看右边
            System.out.println(animals[i].name);
            animals[i].eat();
            animals[i].drink();
            //如果超类想访问子类的方法,需要进行类型转换
            //在转换时为了保证转换的类型相同, 可以用 instanceof 进行判断是否是同一类型
            if (animals[i] instanceof Dog){
                Dog dog= (Dog) animals[i];
                dog.lookHemo();
            }
            if (animals[i] instanceof Chick){
                Chick chick = (Chick) animals[i];
                chick.layEggs();
            }
            if (animals[i] instanceof Swim s) {
                s.swim();
            }
        }
        System.out.println("--------------------------------------------------");
        //2.把超类型作为参数或返回值类型,传递或返回派生类(Dog/Fish/Chick)对象,以扩大方法的应用范围(所有Animal)
        Master master =new Master();
        Dog dog =new Dog("大米",2,"白色","狗狗");
        Fish fish =new Fish("小米",1,"黄色","鱼");
        Chick chick =new Chick("白面",2,"黄色","小鸡");
        master.feed(dog);
        master.feed(fish);
        master.feed(chick);
    }
}

补充


  1. 方法的重载与重写

  • 重载:发生在同一类中,方法名相同,方法的参数不同(类型,顺序)

void show ()//无参

void show (String name ,int age) void show (int age , String name) //有参顺序不同

  • 重写:发生在不同类中(继承或者实现)父子类,方法名相同,参数相同

*重写的方法被调用时,看对象的类型------------------new谁就调谁的,这是规定*

abstract calss Fu (){ abstract void eat() }

class Zi extends Fu(){ void eat(){System.out.println("吃饭")}

  • 重载和重写的特殊情况

  class Aoo{
    void show(){}
  }
  class Boo extends Aoo{ //此类中发生了show方法的重载
    void show(String name){}
  }
  class Boo{ //既没有重载也没有重写
    void show(){}
  }
  class Boo{ //既没有重载也没有重写
    void show(String name){}
  }
  class Boo extends Aoo{ //发生重写了
    void show(){}
  }
  1. 类间关系:

  • 类和类-------------------------------继承

  • 接口和接口-------------------------继承

  • 类和接口----------------------------实现

  1. null:表示空,没有指向任何对象。

  • 若引用的值为null,则该引用不能再进行任何操作了,若操作则发生NullPointerException空指针异常。

  1. 隐式的引用:

this:指代当前对象

super:指代当前对象的超类对象

外部类名.this:指代当前对象的外部类对象

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值