1.10:面向对象(中)续

前言:菜鸟一枚,如有问题欢迎大家在评论区指出,我们一起学习。

1.10.1:抽象类与抽象方法

        当某些事物有共同的特征,但是又不能在父类中给出具体的体现,只能在子类中得到体现。那么父类在声明这些方法时,可以只有方法签名,没有方法体,我们将这种方法成为抽象方法 。在Java中,抽象方法必须包含在抽象类中。我们需要借助 abstract 关键字实现抽象。

示例代码:

public abstract class Animal {
    public abstract void eat();
}
public class Cat extends Animal {
    public void run (){
      	System.out.println("小猫吃鱼和猫粮"); 	 
    }
}
public class CatTest {
 	 public static void main(String[] args) {
        // 创建子类对象
        Cat c = new Cat(); 
       
        // 调用eat方法
        c.eat();
  	}
}

         在前一篇文章中,我们学习到了多态,并使用了普通父类和普通子类来实现多态。实现多态其中最重要的是父类定义方法,子类重写方法。现在我们学习了抽象方法后,父类方法可以不用些方法体。至此,我们学习了第二种实现多态的方法,接下来我们学习如何使用接口实现多态。

1.10.2:接口

        接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并不是类,而是另外一种引用数据类型。接口定义后,类可以通过 implements 关键字来实现该接口,这个类也被称为实现类。

示例代码:

//接口也不能实例化
public interface Person {
     // 灰色的是可以不用写的,接口中声明的属性默认修饰符是 public static final,写和不写都是一样的,所以只需要写String name =  "Tom"
    String NAME = "Tom";
    //我们发现接口中声明的属性是常量,一般都不声明


    //接口中方声明的方法默认修饰符是public abstract
    void sayHello();

    //jdk1.8开始其他修饰的方法

    //default修饰的方法有方法体,不强制要求实现类必须实现
    //default修饰的方法由实现类对象调用
    default void sayHi() {
        System.out.println("Hi");
    }

    //static修饰的方法也由方法体,由接口调用,不允许实现类调用(不同于类中静态方法)
    static void sayHello2() {
        System.out.println("Hello2");
    }
}
public class Teacher implements Person{
    //实现和重写一样
    @Override
    public void sayHello() {
        System.out.println("我是老师");
    }
}
public class Doctor implements Person{
    @Override
    public void sayHello() {
        System.out.println("我是医生");
    }
}

public class Master {
    public void WhoAmI(Person person){
        person.sayHello();
    }
}

public class TestMaster {
    public static void main(String[] args) {
        Person person = new Teacher();
        Doctor doctor = new Doctor();
        Master master = new Master();
        master.WhoAmI(person);
        master.WhoAmI(doctor);
    }
}

注意: 一个实现类如果实现一个接口,则必须实现接口里所有的抽象方法,并且静态方法不能被实现类调用

        运行后发现,WhoAmI()方法传入不同的对象,它们所调用的方法是自己重写后的方法 ,至此,第三种实现多态的方法——利用接口。

实现多态的三种方法:

1.普通父类和普通子类

2.抽象父类和普通子类

3.接口和实现类

        在现在看来,接口跟抽象父类 好像是一样的,无非就是省略了修饰符,不能有其他成员,没有构造器,没有初始化块(没有成员变量,只有常量),那为什么要设计一个接口这种引用数据类型了?因为Java中一个类只能继承一个父类,但是类可以实现多个接口(单继承,多实现),接口的好处是接口不会影响父类。接口也可以继承,并且可以同时继承多个接口。

示例代码:

public interface Father {
    void sayHi();
}
public interface GrandFather {
    void sayHello();
}
public interface Son extends Father,GrandFather{
    void sayGoodbye();
}
public class TestSon implements Son{

    @Override
    public void sayGoodbye() {
        System.out.println("再见");
    }

    @Override
    public void sayHi() {
        System.out.println("你好");
    }

    @Override
    public void sayHello() {
        System.out.println("你好!");
    }
}

注意:虽然实现类 TestSon 只是实现Son接口,但是由于Son接口继承了两个接口,因此在实现类里,我们需要重写三个抽象方法。

1.10.3:接口命名冲突

        我们已经知道类可以同时继承父类和实现接口,或者可以实现多个接口,那么当它们之中有同样命名的方法时,我们到底访问的是哪一个了?

亲爹优先原则:当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的抽象方法重名,子类就近选择执行父类的成员方法。代码如下:

public class Father {
    public void sayHello (){
        System.out.println("你好");
    }
}
public interface Brother {
    default void sayHello(){
        System.out.println("Hello");
    }
}
public class Son extends Father implements Brother{
    @Override
    public void sayHello() {
        Brother.super.sayHello();
    }
}
public class TestSon {
    public static void main(String[] args) {
        Son son = new Son();
        son.sayHello();
    }
}

运行结果: Hello    调用的 Father 接口的 sayHello 方法

当接口和父类方法重名时,不重写,父类优先。重写时,使用 接口名.super.方法名  来调用接口,方法或者直接自己完全重写一个。

 左右为难:当一个类实现多个接口,我们需要做出抉择。代码如下:

public interface Brother {
    default void sayHello(){
        System.out.println("Hello");
    }
}
public interface Sister {
    default void sayHello(){
        System.out.println("幸会");
    }
}
public class Me implements Brother,Sister{
    @Override
    public void sayHello() {
        Sister.super.sayHello();
    }
}

 运行结果:幸会     调用的 Sister 接口的 sayHello 方法

实现两个接口时,若两个接口中有同名方法,则必须重写
重写时,使用  接口名.super.方法名  来指定一个方法进行调用

1.10.4:Comparable接口 

Comparable接口用于比较两个对象的大小,但是我们需要对compareTo()方法进行重写。

public class Worker implements Comparable{
    private String name;
    private int age;
    private String gender;

    public Worker() {
    }

    public Worker(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Worker{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }

    @Override
    public int compareTo(Object o) {
        Worker worker = (Worker) o;
        return this.age - worker.getAge();
    }
}
public class TestWorker {
    public static void main(String[] args) {
        Worker worker1 = new Worker("小白",13,"男");
        Worker worker2 = new Worker("小蓝",14,"女");
        System.out.println(worker1.compareTo(worker2));
    }
}

运行结果: -1

//返回负数时,调用对象小,参数对象大
//返回正数时,调用对象大,参数对象小
//返回0时,一样大

通过重写方法后,让其比较两个对象的 age 属性值大小。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

oooosuperstar

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值