Java研学-抽象

一 抽象

1 为什么抽象

  当父子类具有共性的方法,需要定义在父类中的方法,但是父类无法实现功能,需要由具体的子类来实现,此时需要将父类中定义的共性方法,去掉方法体,变为概念。称这样的方法为抽象方法(没有方法体,能够节省栈内存空间);抽象方法必须定义在抽象类中

// 抽象类
public abstract class Animal {
    // 姓名
    public String name;
    // 年龄
    public int age;
    // 身高
    public int high;
    // 抽象方法
    public abstract void run();
    ...
}

2 抽象类和抽象方法的定义格式

public abstract class 类名{

	public abstract 返回值类型 方法名 ([参数列表]);

}

3 当父类为抽象类时,子类应实现对应的抽象方法或者将子类变为抽象类

// 抽象父类
public abstract class Animal {
    // 姓名
    public String name;
    // 年龄
    public int age;
    // 身高
    public int high;
    // 抽象方法
    public abstract void run();
    ...
}
// 实现父类抽象方法
public class Cat extends Animal{
    private String crawl;
    // 实现继承的抽象类中的抽象方法
    @Override
    public void run() {
        System.err.println("跑");
    }
    ...
}
// 抽象子类继承抽象父类
public abstract class Cat extends Animal{
    ...
}

  ① 当前子类重写父类已实现的方法 称之为重写

  ② 当子类中定义父类抽象方法时,称之为实现(implements)

  ③ 抽象类会增加类与类之间的耦合度

二 接口

1 作用:为已存在的类提供该类不具备的方法

  ① 由于java中只支持单继承,为实现多继承的效果,Java中提出类似“多继承的操作”,也就是多实现接口,避免单继承的局限性

  ② 父类只需要定义概念,有具体的子类实现,因此该方法应该是抽象的

  ③ 由于不能实现多继承,需要使用接口来定义抽象方法,由具体的子类实现

2 接口的定义格式

public interface 接口名{
	抽象方法;
}

3 例子

// 接口中方法默认为抽象方法,abstract可省略
// 可将访问权限修饰符设置为缺省
public interface Door {
    public abstract void open();
    void close();
}

public interface Lock {
    void on();
    void off();
}
// 实现多继承
public class Heart implements Door,Lock{
    @Override
    public void open() {
        System.err.println("打开你的心门");
    }

    @Override
    public void close() {

    }

    @Override
    public void on() {

    }

    @Override
    public void off() {

    }
}

4 可定义在接口中的类成员

  ① 成员变量:默认public static final修饰

  ② 成员方法:默认public abstract修饰

  ③ 构造方法:接口中不能有构造方法

5 普通类,接口,抽象类

比较项 普通类 抽象类 接口
定义关键字 class abstract interface
继承或实现的关键字 extends extends implements
成员字段 常量 变量 常量 变量 常量
构造器 既能定义也能实例化 只能定义,不能实例化 既不能定义也不能实例化
成员方法 普通方法,静态方法 抽象方法,普通方法,静态方法 只能定义抽象方法(abstract可以省略)

  ① 当需要继承属性的时候,推荐使用抽象方法;其余都用接口;(便于定义统一的操作规则)

  ② 当继承类和实现接口同时出现的时候,一定是先继承在实现

public class Heart extends Animal implements Door,Lock{
}

三 多态

1 含义

  同一方法可以根据发送对象的不同而采取多种不同的行为方式,即一个对象的实际类型是确定的,但可指向对象的引用类型有很多,可实现动态编译

2 前提

  类与类之间必须是继承关系,否则会报类型转换异常(ClassCastException),子类重写父类方法(static,属于类不能重写,私有方法,final),父类引用指向子类对象(Father f1 =new son();),多态是方法的多态,属性没有多态性

3 例子

// 父类
public class Person {
    public void run(){
        System.err.println("跑");
    };
}
// 子类
public class Student extends Person{
    @Override
    public void run() {
        // 子类重写父类方法
        System.err.println("小跑");
    }
    // 子类特有方法
    public void eat(){
        System.err.println("吃");
    }
}
// 多态测试类
public class Test {
    public static void main(String[] args) {
        // 对象的实际类型是确定的(指new的对象)
        // new Person();

        // 但指向的引用类型是可变的
        // Student能调用的方法都是自己的或者继承父类的
        Student s1 =new Student();

        // 父类引用指向子类的类型
        // Person父类型,可以指向子类,但不能调用子类特有的方法
        Person s2 =new Student();
        Object s3 =new Student();

        // 在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法
        // 父类调用子类中对父类重写的方法,称这个重写的方法为回调函数
        s2.run();// 小跑

        // 子类继承父类的全部方法 可以输出父类方法和子类方法
        // 子类重写父类方法后 执行子类方法
        s1.run();

        // 对象能执行那些方法,主要看左边的类型,和右边关系不大
        // 调用子类特有方法时需要强转,不能直接调用
        //s2.eat();// 不可用
        s1.eat();// 可用

        // 需要强转,强转后可调用子类特有方法
        ((Student) s2).eat();
    }
}

  ①对象是哪个类的对象:看对象前面写的是什么

  ②对象指向哪个类的引用:看new关键字后面的构造器

四 引用数据类型的转换

1 分类

① 向上溯型(向上造型):将子类的构造器赋值给父类的对象,引用数据类型自转

  父类 对象名 = new 子类([参数列表])

② 向下溯型(向下造型):将父类对象构造器赋值给子类对象,俗称引用数据类型强转

  子类 对象名 =(子类) new 父类([参数])

③ 当创建父类对象,想调用子类特有方法时,需要强转

public class Play {
    public static void main(String[] args) {
        Person person=new Student();
        Student student= (Student) person;
        ((Student) person).eat();
        student.eat();
    }
}

  这段代码首先创建了一个类型为Person的对象person,并将其实例化为Student类型。这是一种向上转型,因为Student是Person的子类。

  然后,将person对象强制转换为Student类型,并将其赋值给student变量。这是一种向下转型,因为我们知道person对象实际上是Student类型的。

  接下来,通过强制转型的方式调用person对象的eat()方法。由于person对象实际上是Student类型的,所以可以调用Student类中的eat()方法。

  最后,通过student变量直接调用eat()方法,这是因为student变量已经是Student类型,可以直接调用Student类中的方法。

五 instanceof运算符

1 含义:判断指定的对象是否是指定类或其子类对象的运算符,结果一定是布尔型

2 格式 :对象 instanceof 类

public class Play {
    public static void main(String[] args) {
        Person person=new Person();
        if(person instanceof Student){
            System.err.println("yes1");
        }else if(person instanceof Person){
            System.err.println("ok1");
        }
        Student student=new Student();
        if(student instanceof Student){
            System.err.println("yes2");
        }else if(student instanceof Person){
            System.err.println("ok2");
        }
    }
}

3 详解

   ① 首先定义了一个Person对象,并使用instanceof操作符检查person对象是否属于Student类。由于person对象是Person类的实例,而不是Student类的实例,所以第一个条件不满足,输出"ok1"。

   ② 接着定义了一个Student对象,并使用instanceof操作符检查student对象是否属于Student类。由于student对象是Student类的实例,所以第一个条件满足,输出"yes2"。

   ③ 总结:instanceof操作符用于检查一个对象是否属于某个类或其子类的实例。如果对象是该类或其子类的实例,则返回true;否则返回false。在这段代码中,由于person对象是Person类的实例,而student对象是Student类的实例,所以输出结果分别为"ok1"和"yes2"。

六 多态的好处

1简化业务代码

2 提高代码复用性

3 instanceof 、implements、interface关键字

  ① instanceof :判断指定对象是否是指定类或其子类对象的运算符,结果一定是布尔型

  ② implements:实现的关键字

  ③ interface:定义接口的关键字

4 Java中面向对象的特征

  封装、继承、多态、抽象

5 使用面向对象的好处

  ① 提高代码安全性 – 封装

  ② 简化代码 – 封装(简化主函数)、继承和抽象(简化子类)、多态(简化业务)

  ③ 提高代码重用性(复用性)-- 继承、抽象、多态

  ④ 减低类与类的耦合度-- 封装

你可能感兴趣的:(#,Java研学,java,开发语言)