Java笔记04:面向对象基础

继承

Java使用extends关键字来实现继承:

class Person {
    private String name;
    private int age;

    public String getName() {...}
    public void setName(String name) {...}
    public int getAge() {...}
    public void setAge(int age) {...}
}

class Student extends Person {
    // 不要重复name和age字段/方法,
    // 只需要定义新增score字段/方法:
    private int score;

    public int getScore() {...}
    public void setScore(int score) {...}
}

通过继承,子类Student获得了父类Person已有的字段与方法,节省了重复编写代码的时间。
Java中所有的类都继承自Object这个类,除了它自身。
private关键字修饰的字段,只能在类中被访问,子类也无法访问,为了让子类也能使用父类的字段,要把修饰符改成protected

多态

在上一篇中讲到构造方法时有提到过方法签名的概念,当一个子类与其父类有着相同的方法签名的方法(修饰符、参数、返回值都相同)时,称之为覆写
注意上篇中讲的重载,并不要求方法签名完全相同,编译器也是根据这个将重载的方法区分开来。覆写则在运行期间动态决定调用的方法,以实现多态。

class Animal {
    public void sound {...}
}
class Cat {
    @Override
    public void sound {
        System.out.println("meow")
    }
}

使用@Override可以让编译器帮我们检查覆写是否正确。

final修饰符:

  • final修饰的字段必须在声明是初始化并且无法被修改,也就是常量
  • final修饰的方法不能被子类覆写
  • final修饰的类不能被继承

抽象类

有时候,如果父类的方法没有实际意义,能不能不写呢?

class Person {
    public void run(); // Compile Error!
}

上述代码会报错。
如果一个方法只定义方法签名,没有实质内容,可以用abstract修饰符把它定义成抽象方法,包含抽象方法的类也必须被声明为抽象类(abstract class)。

abstract class Person {
    public abstract void run();
}

抽象类不能被实例化,方法也是空的,这个类用来干什么的呢?抽象类本身被设计成只能用于被继承,因此,抽象类可以强迫子类实现其定义的抽象方法,否则编译会报错。因此,抽象方法实际上相当于定义了“规范”。
对于抽象类的子类,我们可以用抽象类型去引用它的子类型:

Person s = new Student();
Person t = new Teacher();
s.run();
t.run();

我们可以直接调用它的方法而不必关心具体类型,可以确信抽象类的子类是一定实现了这些方法的。

接口

有一种极端的“抽象类”,它只包含抽象方法,这种东西可以写成接口

interface Person {
    void run();
    String getName();
}

由于接口肯定都是抽象方法了,所以没必要用abstract修饰符。事实上它的方法都默认是public abstract。声明接口用interface
某个类要去实现接口,要用implements关键字。

class Dog implements Animal {
    ...
}
Java中一个类只能继承自一个父类,通过接口则可以实现多重继承,一个类可以实现多个接口。(Python支持多重继承)

接口中还可以有一种default修饰符修饰的默认方法,这种方法可以有一个默认实现,具体实现的类可以不必覆写它。

有时候可能两个人都实现了一个名为Person的类,同时还想引用对方的类来使用。对于这种命名冲突的情况应该怎么办呢?
Java使用包package来解决命名冲突。在定义一个类时,把它的包名写在第一行。
下面是用IDE编写程序时自动创建的代码部分:

package com.company;

public class Main {
    public static void main(String[] args) {

    }
}

与下面某人编写的同名Main类:

package harry;

public class Main {
    public static void main(String[] args) {

    }
}

虽然这两个类同名了,但在运行时,这两个类会使用完整类名,它们的完整名分别是com.company.Mainharry.Main
有时候要使用一个包中的类,一种写法是直接写完整类名,但那样就有点麻烦,我们可以和Python中一样使用import语句。
例如要使用 java.util包中的ArrayList

import java.util.ArrayList;

public class SingleImport {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
    }
}

这个包里还含有很多类,可以使用星号*

import java.util.*;

这样表示把这个包里所有类都导入。

扫码关注:
公众号

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章