文章目錄
1. 多態(polymorphism)
1. 1方法的多態性,
重載和覆寫;
- 重載(overloading):1.方法名相同 2.參數類型和個數至少一個不同 3.返回類型和修飾符可以不同
- 覆蓋(overriding):子類有一個方法,與父類某方法的名稱、返回類型、參數相同,則稱子類方法覆蓋父類方法;注:子類方法不能縮小父類方法的訪問權限
1.2 對象的多態性:
父子類對象的轉換,分爲兩種:
- 父類 父類引用 = 子類實例, 自動;
- 子類 子類引用 = 父類實例, 強制;
2是強制轉化,所以2的發生先有1,舉個例子。
1.3 demo
demo1 父類 父類引用 = 子類實例, 自動
public class Parent {
public void method() {
System.out.println("Parent");
}
}
public class Subclass extends Parent{ //inherit from A
public void method() { //overrride
System.out.println("Subclass");
}
}
public class Main {
public static void main(String[] args) {
Parent p = new Subclass();
p.method();
}
}
運行結果
![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20191012143035790.png
demo2 子類 子類引用= 父類對象 強制
public class Main2 {
public static void main(String[] args) {
Parent p = new Subclass();
Subclass s = (Subclass) p;
s.method();
}
}
![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20191012143716128.png
但是如果沒有1的 父類引用 = 子類對象,而直接強制轉換子類引用 = 父類對象則會報錯。
public class Main3 {
public static void main(String[] args) {
Parent p = new Parent();
Subclass s = p;
s.method();
}
}
表象:
父類的引用指向子類的對象。
成員變量: 編譯看左邊,運行看左邊
編譯看左邊的意思就是父類有的方法和屬性才能去調用
成員方法: 編譯看左邊,運行看右邊
編譯看左邊的意思就是父類有的方法和屬性才能去調用, 但運行的時候是運行的子類的成員方法。
構造方法:先初始化父類,在初始化子類
靜態方法:編譯看左邊,運行看左邊
1.4 總結
一般來說多態存在的前提:
- 要有繼承(inherice)
- 要有重寫(overriding)
- 父類引用指向子類對象
其實,方法(method)的覆寫(Overriding)和重載(overloading)是java多態性的不同表現。overriding是Superclas和subclass之間的polymorphism。overloading是一個class中polymorphism的一種表現。
1.5 instanceof key word
Insatance instanceof class ——> boolen類型
public class Main4 {
public static void main(String args[]) {
Parent p = new Subclass();
System.out.println( p instanceof Parent);
System.out.println( p instanceof Subclass);
}
}
Result
![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20191012145641373.png
2. 抽象類(abstract class)
一個類去繼承一個已經實現好的類的情況一般不可能出現,只能繼承抽象類或實現接口。
2.1 抽象類
abstract class: 只聲明,沒實現。並用abstract關鍵字。
java類:普通類,抽象類:繼承
接口:實現
單繼承,多實現(只能繼承一個父類)
抽象類:
- 和普通類很相似,也是要抽取共性
- 他和普通的類的差別在於抽象類裏面可以定義抽象方法
抽象方法: 訪問修飾符 abstract 返回類型 方法名字(參數類型 參數名);
普通方法:訪問修飾符 返回類型 方法名字(參數類型 參數名){
具體實現代碼
} - 抽象方法必須在抽象類裏面
- 子類必須重寫這個抽象類裏面的抽象方法
一流的廠商出接口 - 抽象類和抽象方法必須有關鍵字abstract
- 抽象類不能被實例化,抽象類的定義就是 爲了被繼承
- 抽象類裏面有構造方法,子類實例化的時候,先初始化父類,在初始化子類。
- 抽象類裏面可以有普通方法,抽象類裏面可以不定義抽象方法
- 抽象類裏面可以定義普通方法,也可以沒有普通方法,但有抽象方法的類必須是抽象類
2.2 demo
// superclass
public abstract class People {
String name;
public abstract void eat();//no method body
}
//subclass
public class Student extends People{
@Override
public void eat() {//override abstract class
System.out.println("Student eats in the school canteen");
}
}
//main()
public class Main {
public static void main(String args[]) {
People p = new Student();
p.eat();
}
}
Result
2.3 抽象類的應用–模板設計模式
這個其實我也不懂,在P209頁java核心技術精講裏有個例子。
這裏舉個相似的例子。
3種類型,student,teacher,worker
student: eat , work , sleep
teacher: eat, work, sleep
work: :eat, work,sleep
設計一個程序,實現三個的功能,並使得不同的類型進行其各自的eat,sleep等功能。
//abstract class
public abstract class People {
String name;
public abstract void eat();
public abstract void work();
public abstract void study();
public abstract void sleep();
//subclass
public class Student extends People{
@Override
public void eat() {
System.out.println("Student eats in the school canteen");
}
@Override
public void work() {
}
@Override
public void study() {
System.out.println("Student studys at school");
}
@Override
public void sleep() {
System.out.println("Student sleeps in the dormitory");
}
}
//subclass
ublic class Teacher extends People{
@Override
public void eat() {
System.out.println("Teacher eats at home");
}
@Override
public void work() {
System.out.println("Teacher teaches studens at school");
}
@Override
public void study() {
// TODO Auto-generated method stub
}
@Override
public void sleep() {
System.out.println("Teacher sleeps at home");
}
}
//subclass
public class Worker extends People{
@Override
public void eat() {
System.out.println("worker eats on the site");
}
@Override
public void work() {
System.out.println("worker works on the site");
}
@Override
public void study() {
// TODO Auto-generated method stub
}
@Override
public void sleep() {
System.out.println("worker sleeps on the site");
}
}
//main
public class Main {
public static void main(String[] args) {
Student stu = new Student();
Action(stu);
System.out.println("*********************");
People tea = new Teacher();
Action(tea);
System.out.println("*********************");
People wor = new Worker();
Action(wor);
}
public static void Action(People p) {
p.eat();
p.work();
p.study();
p.sleep();
}
}
Result
繼續擴展實現其他職業,只需要添加相應class, override相應的abstract method就可以,而不需要很多的代碼量。抽象類起到了定義模板的功能。
2.4 abstract不能和那些關鍵字一起出現:
private:private不能被繼承
static:抽象方法一旦被靜態所修飾,可以通過類名.方法名來訪問
Final: 被final修飾的屬性是常量被修改,方法不被重寫,類不被繼承
3 接口 (interface)
3.1 interface
當一個類定義時全部由抽象方法和全局常量組成,那麼這種類就稱爲接口(interface)。
3.2 特點 characteristic
圖來自於 b站視頻
3.3 demo
3.3.1 demo1 單繼承,多實現
class subclass [extends superclass] [implements interface 1 , interface 2 , interface3…]
即就是:單繼承,多實現,先繼承,後實現。
Subclass
//interfaceA
public interface InterfaceA {
public static final String name ="InterfaceA";
public abstract void print();
}
//interfaceB
public interface InterfaceB {
public abstract void get();
}
//superclass
public class Superclass {
Superclass(){
System.out.println("Superclass");
}
}
//subclass
public class Subclass extends Superclass implements InterfaceA,InterfaceB {
@Override
public void get() {
System.out.println("InterfaceB get()");
}
@Override
public void print() {
System.out.println("print()");
}
}
//main()
public class Main {
public static void main(String[] args) {
Subclass s = new Subclass();
s.get();
InterfaceA ia = new Subclass();
ia.print();
}
}
Result
因爲interface中只有abstract method和全局常量,所以可以簡寫。
完整定義
interface A{
public static final String name = "hello";
public abstract void print();
}
簡化定義
interface A{
public String name = "hello";
public void print();
}
3.3.2 demo2 接口實現多繼承
//interface
public interface A {
public String name = "ZhangSan";
public void printA();
}
//interface B
public interface B {
public void printB();
}
//interface C extends A, B
public interface C extends A, B{
public void printC();
}
//subclass implements A,B,C
public class Subclass implements A,B,C{
@Override
public void printC() {
System.out.println(C.name);
}
@Override
public void printB() {
System.out.println("print B");
}
@Override
public void printA() {
System.out.println("print A");
}
}
//main()
public class Main {
public static void main(String args[]) {
A a = new Subclass();
a.printA();
B b = new Subclass();
b.printB();
C c = new Subclass();
c.printC();
}
}
Result
3.3.3 demo3 使用接口定義標準
比如USB接口,具體的金士頓(Kingston)和閃迪(Sandisk)等,其中最很重要是讀寫功能。
//USB interface
public interface USB {
public void read();
public void write();
}
// Kingston implements USB
public class Kingston implements USB{
@Override
public void read() {
System.out.println("Kingston reads the doc line by line ");
}
@Override
public void write() {
System.out.println("Kinston writes the doc line by line");
}
}
//Sandisk implements USB
public class Sandisk implements USB{
@Override
public void read() {
System.out.println("Sandisk reads the doc byte by byte");
}
@Override
public void write() {
System.out.println("Sandisk writes the doc byte by byte");
}
}
//Computer
public class Computer {
public void plugin(USB b) {
b.read();
b.write();
}
}
//main()
public class Main {
public static void main(String[] args) {
Computer pc = new Computer();
USB kingston = new Kingston();
pc.plugin(kingston);
Sandisk sandisk = new Sandisk();
pc.plugin(sandisk);
}
}
Result
不管多少種USB設備,只要實現了USB interface都可以在computer上使用,所以interface就相當於制訂了一個操作標準。
demo4和demo5來自java核心技術精講
3.4 interface的實際作用 – 工廠設計模式(Factory)
demo3.5 interface的世紀作用—代理設計模式(proxy)
4. conclusion
普通類,抽象類和接口的區別