欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Java中的封裝、繼承、多態(tài)

 更新時間:2017年01月17日 16:55:39   作者:追夢子  
本文主要介紹了Java中的封裝、繼承、多態(tài)的相關(guān)知識,具有一定的參考價值,下面跟著小編一起來看下吧

封裝

在如何理解面向?qū)ο筮@篇文章中,提到所謂的封裝就是“功能都給你做好了,你不必去理解它是怎么寫出來的,直接使用即可?!薄5愕们宄稽c(diǎn),那就是這句話是相對于使用者來說的,而作為開發(fā)者,封裝就得我們自己來干。

那么作為開發(fā)者,我們應(yīng)該如何去封裝呢?其實你應(yīng)該反過來問,他們應(yīng)該如何去使用,這樣一想會簡單很多,作為使用者,自然是希望越簡單越好,也就是說,一些復(fù)雜的東西,我們不應(yīng)該讓使用者去操作,那也就是說我們應(yīng)該把復(fù)雜的,以及不必要的參數(shù)給它封死,不讓使用者去操作。

為什么不讓使用者去操作?

因為往往使用者是不太專業(yè)的,如果暴露太多的接口給他們,就很有可能出現(xiàn)一些稀奇古怪的問題,好比一個不會做水煮魚的,如果讓他去做那肯定是不好的,那怎么辦,給他買一包水煮魚的調(diào)料,讓他直接放進(jìn)鍋里就好,這樣就減少了不必要的麻煩。我們封裝程序也是這樣,把復(fù)雜的代碼封死,不讓操作者去操作,以免出錯。

比如下面這個例子:

class Average{
 private int[] fractions = new int[3]; //分?jǐn)?shù)
 private int average = 0; //平均分
 public void setFraction(int[] fraction){
  fractions = fraction;
 }
 public double getAverage(){
  for(int cell:fractions){
   average += cell;
  }
  return (double) (average / fractions.length);
 }
}
class app{
 public static void main(String[] args){
  int[] a = {50,40,50};
  Average average = new Average();
  average.setFraction(a); //設(shè)置分?jǐn)?shù)
  double n = average.getAverage(); //獲取平均分
  System.out.println(average.average); //報錯
  System.out.println(n); //46.0
 }
}

提示:Java通過private設(shè)置私有變量,通過public將變量設(shè)置成公開的。

這里我們之所以將分?jǐn)?shù)和平均分設(shè)置成私有變量是為了防止使用者誤操作,而且也不必讓使用者知道有這么一個變量,只需要讓使用者知道怎么去設(shè)置分?jǐn)?shù),和獲取平均分就好了。

當(dāng)然這只是一個很基礎(chǔ)的封裝,如果想封裝出一個好的程序,還得多費(fèi)一些心思。

繼承

拿貓和狗來說,它們都是動物,而且它們有一些共同點(diǎn),比如:名字,年齡,聲音,吃等。把這段話寫成代碼就是下面這個樣子。

class Animal{
 private String name;
 private int age;

 public void setName(String name){
  this.name = name;
 }
 public void setAge(int age){
  this.age = age;
 }
 public String getName(){
  return this.name;
 }
 public int getAge(){
  return this.age;
 }
}
class Cat extends Animal{
 public void voice(){
  System.out.println(super.getName() + " 喵");
 }
 public void eat(){
  System.out.println(super.getName() + " fish");
 }
}
class Dog extends Animal{
 public void voice(){
  System.out.println(super.getName() + " 汪");
 }
 public void eat(){
  System.out.println(super.getName() + " Bone");
 }
}
class app{
 public static void main(String[] args){
  Cat cat = new Cat();
  cat.setName("貓大王"); //Cat本身沒有setName方法,但是它的基類有,所以java解析器會到Cat的基類那里拿
  cat.voice();
  Dog dog = new Dog();
  dog.setName("大黑");
  dog.setAge(13);
  dog.voice();
  System.out.println(dog.getName() + dog.getAge());
 }
}

------Output------
貓大王 喵
大黑 汪
大黑13

提示:Java通過extends關(guān)鍵字來實現(xiàn)繼承,父類中通過private定義的變量和方法不會被繼承,也就是你不能在子類中直接操作父類通過private定義的變量以及方法。

在上面代碼中,我們可以看到,Cat和Dog并沒有定義setName、setAge、getName、getAge方法,但是我們依然可以在Cat和Dog類中使用,這是因為我們通過extends關(guān)鍵字繼承了Animal類,因此在Animal中定義的變量和方法,我們可以在子類中直接使用,除private定義的變量和方法。

反過來說,姓名和年齡是貓和狗的基本信息也是它們的共同特性。

重寫父類方法或變量

一般重寫父類方法,是因為你把貓當(dāng)成是一個基類,而將狗繼承自貓類。看似這很好笑,但如果你去翻翻你的代碼,這種情況多如牛毛。當(dāng)然,如果你不需要繼承,那就另說了。那么如果碰到這種情況,我們怎么重寫基類呢?很簡單,在子類中定義一個和父類中一樣的方法,如下面這樣:

class Animal{
 private String name;
 private int age;

 public void setName(String name){
  this.name = name;
 }
 public void setAge(int age){
  this.age = age;
 }
 public String getName(){
  return this.name;
 }
 public int getAge(){
  return this.age;
 }
}
class Dog extends Animal{
 public String getName(){
  return super.getName() + "2";
 }
 public void voice(){
  System.out.println(super.getName() + " 汪");
 }
 public void eat(){
  System.out.println(super.getName() + " Bone");
 }
}
class app{
 public static void main(String[] args){
  Dog dog = new Dog();
  dog.setName("大黑");
  System.out.println(dog.getName()); //執(zhí)行的是Dog中的getName方法
 }
}

提示:通過super可以在子類中直接調(diào)用父類的方法以及變量,通過this調(diào)用當(dāng)前類。

我覺得把這叫做重寫不太好,因為如果從本質(zhì)來講,它不算重寫,只是Java尋找變量以及方法的規(guī)則罷了。Java會先看一下,自己身上有沒有某個變量或方法,如果沒有,它會接著到父類中找,如果父類中還是沒有,那么它又會到更上一級中找,如果一直找上去都沒有,那么才報錯。

在重寫父類時,需要注意一下,重寫時,方法的返回值類型必須和父類中定義的一致,如果是數(shù)字類型,只要重寫時類型不大于父類中定義的,那么也是可以的。比如下面這樣就會報錯

class Animal{
 private String name;
 public void setName(String name){
  this.name = name;
 }
 public String getName(){
  return this.name;
 }
}
class Dog extends Animal{
 public int getName(){ //和父類中的getName返回值不同,報錯
  return 123;
 }
}
class app{
 public static void main(String[] args){
  Dog dog = new Dog();
  System.out.println(dog.getName());
 }
}

另外還需要注意,如果重寫時,和父類中的參數(shù)不一致,則會發(fā)生意想不到的事,比如下面這個

class Animal{
 private String name;

 public void setName(String name){
  this.name = name;
 }
 public String getName(String hello){
  return this.name + hello;
 }
}
class Dog extends Animal{
 public String getName(){
  return "123";
 }
}
class app{
 public static void main(String[] args){
  Dog dog = new Dog();
  dog.setName("大黑");
  System.out.println(dog.getName("hello"));
 }
}

------Output------
大黑hello

可以看到當(dāng)我們給getName傳達(dá)了參數(shù)時,執(zhí)行的是Animal中的方法,而非Dog中的getName方法,也就是說如果參數(shù)不一致最后執(zhí)行的可能就不是重寫的那個方法。另外也不可將父類公開的方法或變量改成私有(如將public改成private),否則也會報錯,我估計是Java有一套覆蓋規(guī)則,如果沒有達(dá)到條件就不會進(jìn)行覆蓋。

總結(jié)來,覆蓋父類方法或變量時,對其只能更寬松,而反過來則不行。

多態(tài)

先來幾個例子,再講理論

class Animal{
 public int age = 5;

 public int getAge(){
  return age;
 } 
}
class Dog extends Animal{
 public int age = 8;

 public int getAge(){
  return age + 2;
 }
}
class app{
 public static void main(String[] args){
  Animal dog = new Dog();
  System.out.println(dog.age);
 }
}

------Output------
5

看Animal dog = new Dog();這么一句話,可以發(fā)現(xiàn)它們的類型并不一樣,但卻可以正常運(yùn)行,之所以可以運(yùn)行是因為,Dog類是Animal的子類,而父類是包括子類的。我們說動物,那么狗是不是就是動物中的一員呢,這是肯定的,而這里之所以如果運(yùn)行也正是這個理。

不過需要注意一下,通過這種方式創(chuàng)建的對象,在獲取實例變量時,獲取到的是父類中的實例變量,如果是方法,則看子類中是否存在和父類中同名的方法,如果存在則使用子類中的方法,但是如果子類中有某個方法,而父類中沒有,那么就會報錯。如下這段代碼就會報錯

class Animal{
 public int age = 5;
 public int getAge(){
  return age;
 }
}
class Dog extends Animal{
 public int age = 8;

 public int getAge(){
  return age + 2;
 }
 public setAge(int a){
  this.age = a;
 }
}
class app{
 public static void main(String[] args){
  Animal dog = new Dog();
  System.out.println(dog.setAge(5));
 }
}

因為父類中沒有setAge這個方法,因此會報錯。

也就是說,通過這種方式來寫,只能達(dá)到覆蓋方法的效果,沒有其他的功能。

這里所謂的多態(tài),在程序中你可以理解成,一個方法,它可以有不同的效果,那怎么實現(xiàn)不同的效果呢?在java中通過切換類型來實現(xiàn)(不一定正確)。

多態(tài)有什么用?

還是再來看幾個例子吧

class Animal{
 public int age = 5;

 public int getAge(){
  return age;
 }
}
class Dog extends Animal{
 public int getAge(){
  return age + 2;
 }
}
class Cat extends Animal{
 public int getAge(){
  return age + 3;
 }
}
class app{
 public static void main(String[] args){
  Animal dog = new Dog();
  Animal cat = new Cat();

  System.out.println(dog.getAge());
  System.out.println(cat.getAge());
 }
}

------Output------
7
8

可以看到,它會根據(jù)自身執(zhí)行不同的方法。不過話說回來,這并不能代表什么,畢竟我們按照正常情況來創(chuàng)建,效果也可以一樣,不過還真有它的用武之處,比如下面這段代碼

class Animal{
 public int age = 5;

 public int getAge(){
  return age;
 }
}
class Dog extends Animal{
 public int getAge(){
  return age + 2;
 }
}
class Cat extends Animal{
 public int getAge(){
  return age + 3;
 }
}
class app{
 public static void main(String[] args){
  Animal[] animals = new Animal[2];
  animals[0] = new Dog();
  animals[1] = new Cat();

  System.out.println(animals[0].getAge());
  System.out.println(animals[1].getAge());
 }
}

------Output------
7
8

這段代碼和上面一段差不多,不過這段代碼中用的是一個數(shù)組,這種情況就比較適合使用多態(tài)了,不然好像沒有其他辦法來弄了吧(初學(xué)java,不太懂)。在這里面多態(tài)不僅僅只是指一個方法有不同的效果,在這里還指類型的多樣性。

以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!

相關(guān)文章

  • Java定時任務(wù)ScheduledThreadPoolExecutor示例詳解

    Java定時任務(wù)ScheduledThreadPoolExecutor示例詳解

    這篇文章主要介紹了Java定時任務(wù)ScheduledThreadPoolExecutor示例詳解,這里使用scheduleAtFixedRate方法安排一個任務(wù),該任務(wù)是一個 Runnable 匿名類,其run方法中調(diào)用了new LoginViewTimeTask().loginStatisticsHandle()方法,需要的朋友可以參考下
    2023-11-11
  • 圖解JVM垃圾內(nèi)存回收算法

    圖解JVM垃圾內(nèi)存回收算法

    這篇文章主要介紹了圖解JVM垃圾內(nèi)存回收算法,由于年輕代堆空間的垃圾回收會很頻繁,因此其垃圾回收算法會更加重視回收效率,下面小編就和大家來一起學(xué)習(xí)一下吧
    2019-06-06
  • String?concat(String?str)使用小結(jié)

    String?concat(String?str)使用小結(jié)

    這篇文章主要介紹了String?concat(String?str)使用小結(jié),在了解concat()之前,首先需要明確的是String的兩點(diǎn)特殊性,一是長度不可變二是值不可變,本文給大家詳細(xì)講解,需要的朋友可以參考下
    2022-11-11
  • Java手寫持久層框架的詳細(xì)代碼

    Java手寫持久層框架的詳細(xì)代碼

    這篇文章主要介紹了Java手寫持久層框架,本文適合有一定java基礎(chǔ)的同學(xué),通過自定義持久層框架,可以更加清楚常用的mybatis等開源框架的原理,需要的朋友可以參考下
    2022-08-08
  • Springboot項目基于Devtools實現(xiàn)熱部署步驟詳解

    Springboot項目基于Devtools實現(xiàn)熱部署步驟詳解

    這篇文章主要介紹了Springboot項目基于Devtools實現(xiàn)熱部署,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-06-06
  • 通過java.util.TreeMap源碼加強(qiáng)紅黑樹的理解

    通過java.util.TreeMap源碼加強(qiáng)紅黑樹的理解

    通過分析java.util.TreeMap源碼來對經(jīng)典問題紅黑樹加強(qiáng)理解和理清思路。
    2017-11-11
  • Java編程Socket實現(xiàn)多個客戶端連接同一個服務(wù)端代碼

    Java編程Socket實現(xiàn)多個客戶端連接同一個服務(wù)端代碼

    這篇文章主要介紹了Java編程Socket實現(xiàn)多個客戶端連接同一個服務(wù)端代碼,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • Java中的maven和gradle的比較與使用詳解

    Java中的maven和gradle的比較與使用詳解

    這篇文章主要介紹了maven和gradle的比較與使用,Maven使用基于XML的配置,Gradle采用了領(lǐng)域特定語言Groovy的配置,在Maven中要引入一個依賴,需要的朋友可以參考下
    2022-04-04
  • servlet實現(xiàn)文件上傳、預(yù)覽、下載、刪除功能

    servlet實現(xiàn)文件上傳、預(yù)覽、下載、刪除功能

    這篇文章主要為大家詳細(xì)介紹了servlet實現(xiàn)文件上傳、預(yù)覽、下載、刪除功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • JDK環(huán)境變量配置教程分享

    JDK環(huán)境變量配置教程分享

    這篇文章主要為大家分享了JDK環(huán)境變量配置教程,JDK環(huán)境變量的配置,是java開發(fā)中必備的配置
    2016-05-05

最新評論