java面向对象编程_包_继承_多态_重载和重写_抽象类_接口_this和super(3)

简介: java面向对象编程_包_继承_多态_重载和重写_抽象类_接口_this和super(3)

接口

基本语法

//定义接口类型
interface IAnimal{
    //抽象方法
    // public static final 字段
}

使用interface 定义一个接口

image.png

接口中的方法一定是抽象方法, 因此可以省略 abstract

接口中的方法一定是public, 因此可以省略public

image.png

接口中只能包含抽象方法,对于字段来说, 接口中只能包含静态常量(final static)

interface IAnimal{
    // public static final 字段 可以省略public static final
    String name = "animal"; //因为是final 修饰,需要赋初值!
    int age = 18;
    //抽象方法
    public abstract void speak();
    void eat(); //省略public abstract
}

子类 使用 implements继承接口。 此时表达的含义不再是 “扩展”, 而是 “实现”


在调用的时候同样可以创建一个接口的引用, 对应到一个子类的实例。


接口不能单独被实例化。


扩展(extends)vs 实现(implements)


扩展指的是当前已经有一定的功能了, 进一步扩充功能。

实现指的是当前啥都没有, 需要从头构造出来。


接口不能用限定符修饰

image.png

实现多个接口

接口弥补了java无法多继承的缺陷!

我们可以实现多个接口

基本语法


有时候我们需要让一个类同时继承自多个父类. 这件事情在有些编程语言通过 多继承 的方式来实现的。然而 Java 中只支持单继承, 一个类只extends 一个父类。 但是可以同时实现多个接口, 也能达到多继承类似的效果。

class 类名 implement interfa1,interface2,....interfaceN{
     //实现所有接口中的方法!
}

实例一

下面我们通过类来表示张三

//实现多个接口
interface IAnimal{
    String name = "animal";
    int age = 18;
    void speak();
    void eat();
}
interface IPeople{
    String iQ = "140";
    void study();
}
class Zhansan implements IAnimal,IPeople{
    @Override
    public void speak() {
        System.out.println("Speak Chinese!");
    }
    @Override
    public void eat() {
        System.out.println("Eat food!");
    }
    @Override
    public void study() {
        System.out.println("Study java!");
    }
}
public class Test_6 {
    public static void main(String[] args) {
        Zhansan zhansan = new Zhansan();
        zhansan.eat();
        zhansan.speak();
        zhansan.study();
    }
}

image.png

实例二

现在我们通过一个类来表示一组动物。

class Animal { 
  protected String name; 
    public Animal(String name) { 
        this.name = name; 
    } 
}

另外我们再提供一组接口, 分别表示 “会飞的”, “会跑的”, “会游泳的”。

interface IFlying { 
    void fly(); 
} 
interface IRunning { 
    void run(); 
} 
interface ISwimming { 
    void swim(); 
}

接下来我们创建几个具体的动物

猫, 是会跑的。

class Cat extends Animal implements IRunning { 
    public Cat(String name) { 
        super(name); 
    } 
    @Override 
    public void run() { 
        System.out.println(this.name + "正在用四条腿跑"); 
    } 
}

image.png


鱼, 是会游的。

class Fish extends Animal implements ISwimming { 
    public Fish(String name) { 
        super(name); 
    } 
    @Override 
    public void swim() { 
        System.out.println(this.name + "正在用尾巴游泳"); 
    } 
}

image.png

青蛙, 既能跑, 又能游(两栖动物)

class Frog extends Animal implements IRunning, ISwimming { 
    public Frog(String name) { 
        super(name);
    } 
    @Override 
    public void run() { 
        System.out.println(this.name + "正在往前跳"); 
    } 
    @Override 
    public void swim() { 
        System.out.println(this.name + "正在蹬腿游泳"); 
    } 
}

image.png

提示,IDEA中使用 ctrl + i 快速实现接口

image.png


还有一种神奇的动物, 水陆空三栖, 叫做 “鸭子”

class Duck extends Animal implements IRunning, ISwimming, IFlying { 
    public Duck(String name) { 
        super(name); 
    } 
    @Override 
    public void fly() { 
        System.out.println(this.name + "正在用翅膀飞"); 
    } 
    @Override 
    public void run() { 
        System.out.println(this.name + "正在用两条腿跑"); 
    } 
    @Override 
    public void swim() { 
        System.out.println(this.name + "正在漂在水上"); 
    } 
}


image.png

上面的代码展示了 Java面向对象编程中最常见的用法: 一个类继承一个父类, 同时实现多种接口。


继承表达的含义是 is - a 语义, 而接口表达的含义是 具有xxx 特性 。


猫是一种动物, 具有会跑的特性。

青蛙也是一种动物, 既能跑, 也能游泳

鸭子也是一种动物, 既能跑, 也能游, 还能飞

这样设计有什么好处呢?


时刻牢记多态的好处, 让程序猿忘记类型. 有了接口之后, 类的使用者就不必关注具体类型, 而只关注某个类是否具备某种能力!


例如, 现在实现一个方法, 叫 “散步”

public static void walk(IRunning running) { 
    System.out.println("我带着伙伴去散步"); 
    running.run(); 
}

在这个walk方法内部, 我们并不关注到底是哪种动物, 只要参数是会跑的, 就行

Cat cat = new Cat("小猫"); 
walk(cat); 
Frog frog = new Frog("小青蛙"); 
walk(frog);


image.png

甚至参数可以不是 “动物”, 只要会跑


class Robot implements IRunning { 
    private String name; 
    public Robot(String name) { 
        this.name = name; 
    } 
    @Override 
    public void run() { 
        System.out.println(this.name + "正在用轮子跑"); 
    } 
} 
Robot robot = new Robot("机器人"); 
walk(robot);

image.png


接口的使用实例

我们java系统包中的很多类都实现了很多接口,使得该类具有某种属性


给对象排序!

//创建student类
class Student{
    private String name;
    private double score;
    public Student(String name,double score){
      this.name = name;
      this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}
public static void main(String[] args) {
  //学生对象数组
        Student[] students = new Student[]{
                new Student("张三",88.7),
                new Student("李四",67),
                new Student("王五",98),
        };
        Arrays.sort(students); //排序
        System.out.println(students);
    }

显然,我们无法排序对象类型的数据,

报异常,说我们Student类没有实现Comparable接口!

image.png

Comparable接口中的抽象方法 compareTo

方法详细信息


int compareTo(T o)将此对象与指定的对象进行比较以进行排序。 返回一个负整数,零或正整数,因为该对象小于,等于或大于指定对象。


实现程序必须确保sgn(x.compareTo(y)) == -sgn(y.compareTo(x))所有x和y。 (这意味着x.compareTo(y)必须抛出异常if y.compareTo(x)引发异常。)


实施者还必须确保关系是可传递的: (x.compareTo(y)>0 && y.compareTo(z)>0)表示x.compareTo(z)>0。


最后,实施者必须确保x.compareTo(y)==0意味着sgn(x.compareTo(z)) == sgn(y.compareTo(z)) ,对于所有z 。


强烈建议,但不要严格要求(x.compareTo(y)==0) == (x.equals(y)) 。 一般来说,任何实现Comparable接口并违反这种情况的类应清楚地表明这一点。 推荐的语言是“注意:此类具有与equals不一致的自然排序”。


在前面的描述中,符号sgn( ) 表达式表示数学符号函数,其定义根据表达式的值是否为负,零或正返回的-1一个,0,或1。


参数

o -要比较的对象。

结果

负整数,零或正整数,因为该对象小于,等于或大于指定对象。

异常

NullPointerException- 如果指定的对象为空

ClassCastException- 如果指定的对象的类型阻止它与该对象进行比较。


看到这么多文字,是不是头都大了!

没有关系,bug郭也头大,不过我知道咋用

//创建student类并且实现Comparable接口
class Student implements Comparable{
    private String name;
    private double score;
    public Student(String name,double score){
      this.name = name;
      this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
    @Override  //实现compareTo方法
    public int compareTo(Object o) {
        Student s = (Student)o; //对o强转, o指的是待比较对象
        if (this.score > s.score) {    //当前对象的score值大
            return -1;
        } else if (this.score< s.score) { //对象o的score值大
            return 1;       
        } else {
            return 0;
        }
    }
}

我们可以看到,这时排的升序,如果要降序就只需将大于号变成小于号即可!

image.png

在 sort 方法中会自动调用compareTo 方法. compareTo 的参数是 Object , 其实传入的就是 Student类型的对象.

然后比较当前对象和参数对象的大小关系(按分数来算).

如果当前对象应排在参数对象之前, 返回小于0 的数字;

如果当前对象应排在参数对象之后, 返回大于 0 的数字;

如果当前对象和参数对象不分先后, 返回0;


注意事项: 对于 sort 方法来说, 需要传入的数组的每个对象都是 “可比较” 的, 需要具备compareTo这样的能力. 通过重写compareTo 方法的方式, 就可以定义比较规则。

为了进一步加深对接口的理解, 我们可以尝试自己实现一个sort方法来完成刚才的排序过程(使用冒泡排序)!


public static void sort(Comparable[] array) { 
    for (int bound = 0; bound < array.length; bound++) { 
        for (int cur = array.length - 1; cur > bound; cur--) { 
            if (array[cur - 1].compareTo(array[cur]) > 0) { 
                // 说明顺序不符合要求, 交换两个变量的位置 
                Comparable tmp = array[cur - 1]; 
                array[cur - 1] = array[cur]; 
                array[cur] = tmp; 
            } 
        } 
    } 
}

image.png


接口间的继承

接口可以继承一个接口, 达到复用的效果. 使用extends关键字!

interface IAmphibious extends IRunning, ISwimming {
}
class Frog implements IAmphibious {
    @Override
    public void run() {
        System.out.println("Frog run!");
    }
    @Override
    public void swim() {
        System.out.println("Frog swim!");
    }
}
public class Test_1 {
    public static void main(String[] args) {
           Frog frog = new Frog();
           frog.run();
           frog.swim();
    }
 }

image.png


通过接口继承创建一个新的接口 IAmphibious 表示 “两栖的”. 此时实现接口创建的 Frog类, 就继续要实现 run 方法,也需要实现 swim方法!


接口间的继承相当于将多个接口合并在一起!



bug郭
+关注
目录
打赏
0
0
0
0
9
分享
相关文章
java中重载和多态的区别
本文详细解析了面向对象编程中多态与重载的概念及其关系。多态是OOP的核心,分为编译时多态(静态多态)和运行时多态(动态多态)。编译时多态主要通过方法重载和运算符重载实现,如Java中的同名方法因参数不同而区分;运行时多态则依赖继承和方法重写,通过父类引用调用子类方法实现。重载是多态的一种形式,专注于方法签名的多样性,提升代码可读性。两者结合增强了程序灵活性与扩展性,帮助开发者更好地实现代码复用。
38 0
Java方法重写(Override)与重载(Overload)的详细对比
在Java编程中,多态性是面向对象编程的核心概念之一。Java通过两种重要的机制来实现多态:方法重写(Override)和方法重载(Overload)。虽然这两个概念都与方法的不同实现有关,但它们在本质上有很大的区别。本文将详细对比这两种机制,帮助开发者更好地理解和应用它们。
156 5
|
3月前
|
Java 面向对象编程的三大法宝:封装、继承与多态
本文介绍了Java面向对象编程中的三大核心概念:封装、继承和多态。
269 15
|
5月前
|
Java基础(13)抽象类、接口
本文介绍了Java面向对象编程中的抽象类和接口两个核心概念。抽象类不能被实例化,通常用于定义子类的通用方法和属性;接口则是完全抽象的类,允许声明一组方法但不实现它们。文章通过代码示例详细解析了抽象类和接口的定义及实现,并讨论了它们的区别和使用场景。
Java零基础-抽象类详解
【10月更文挑战第17天】Java零基础教学篇,手把手实践教学!
82 2
Java零基础-抽象类详解
【10月更文挑战第15天】Java零基础教学篇,手把手实践教学!
56 2
Java零基础-多态详解
【10月更文挑战第10天】Java零基础教学篇,手把手实践教学!
103 4
Java 重写(Override)与重载(Overload)详解
在 Java 中,重写(Override)和重载(Overload)是两个容易混淆但功能和实现方式明显不同的重要概念。重写是在子类中重新定义父类已有的方法,实现多态;重载是在同一类中定义多个同名但参数不同的方法,提供多种调用方式。重写要求方法签名相同且返回类型一致或为父类子类关系,而重载则关注方法参数的差异。理解两者的区别有助于更好地设计类和方法。
718 1
【Java基础面试十八】、说一说重写与重载的区别
这篇文章阐述了Java中重写与重载的区别:重载是同一个类中方法名相同但参数列表不同的方法之间的关系,而重写是子类中方法与父类中相同方法名和参数列表的方法之间的关系,且子类的返回值应小于等于父类,访问修饰符应大于等于父类。
【Java基础面试十八】、说一说重写与重载的区别
在 Java 中,重写(Override)和重载(Overload)是两种不同的概念,用于实现多态性。它们有着不同的作用和使用场景。
在 Java 中,重写(Override)和重载(Overload)是两种不同的概念,用于实现多态性。它们有着不同的作用和使用场景。