亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

java溫故而知新(9)OOP(面向對象編程)理念

2019-11-14 15:31:54
字體:
來源:轉載
供稿:網友

Object   Oriented   PRogramming   (面向對象的程序設計)

1、定義

面向對象程序設計(OOP)的具體定義很難下,也很容易因此而引起爭論,在   Object-Oriented   Frequently  Asked   Questions   (OO   FAQ)   中就有好幾種不同的定義。這里就按照   Grady   Booch   [1994]   的定義:“面向對象程序設計是程序結構的一種實現方法,在這種方法下,程序由互相協作的對象組成,這些對象是某個類的實例,而這些類又是通過繼承關系組成的類的分級結構的成員。

2、要素

面向對象的設計(object   oriented   design)都包含以下幾個要素:  
  •   對象(Object):包含一定的數據結構和狀態的實體。  

  •   操作(Operation):作用于對象的行為,如訪問和處理對象的狀態。  

  •   封裝(Encapsulation):定義對象和操作,只提供抽象的接口,并隱藏它們的具體實現。   

  •   繼承(Inheritance):通過繼承現有類型的性質,創建新的數據類型,而不影響原有數據類型。  

  •   多態性(Polymorphism):判定數據類型集合中各類型的區別,使程序可以按照它們的共同特性來書寫。  

          OOP 的繼承從理論上講是模仿人的思考方法,將對象分類,如:car,bus   這兩個數據類型是從數據類型vehicle   繼承而來的,它們作為   vehicle   的一類,自然繼承了   vehicle   的特性,同時具有自身獨有的特性;而   wheel   卻不是   vehicle   的一類,只是   vehicle   的一個組成部份,因此不是從   vehicle   繼承而來。同樣,vehicle   有一些操作,如   start,reverse,   car和bus也繼承下來,如果必要,也可加上自己獨有的操作,如   drive_at_200mph。但在實際程序中,人們往往忽視了面向對象的內涵,甚止于   C++   這些語言玩了好幾年,也只是用上了面向對象的語法,而沒有形成面向對象的思考方法。

 3、要素詳解

1)對象與對象引用

為便于說明,我們先定義一個簡單的類:

       class Vehicle {         int passengers;               int fuelcap;         int mpg;                   }

有了這個模板,就可以用它來創建對象:

       Vehicle veh1 = new Vehicle();

通常把這條語句的動作稱之為創建一個對象,其實,它包含了四個動作。

1)右邊的“new Vehicle”,是以Vehicle類為模板,在堆空間里創建一個Vehicle類對象(也簡稱為Vehicle對象)。

2)末尾的()意味著,在對象創建后,立即調用Vehicle類的構造函數,對剛生成的對象進行初始化。構造函數是肯定有的。如果你沒寫,java會給你補上一個默認的構造函數。

3)左邊的“Vehicle veh 1”創建了一個Vehicle類引用變量。所謂Vehicle類引用,就是以后可以用來指向Vehicle對象的對象引用。

4)“=”操作符使對象引用指向剛創建的那個Vehicle對象。

我們可以把這條語句拆成兩部分:

Vehicle veh1;

veh1 = new Vehicle();

效果是一樣的。這樣寫,就比較清楚了,有兩個實體:一是對象引用變量,一是對象本身。

       在堆空間里創建的實體,與在數據段以及??臻g里創建的實體不同。盡管它們也是確確實實存在的實體,但是,我們看不見,也摸不著。不僅如此,

       我們仔細研究一下第二句,找找剛創建的對象叫什么名字?有人說,它叫“Vehicle”。不對,“Vehicle”是類(對象的創建模板)的名字。

       一個Vehicle類可以據此創建出無數個對象,這些對象不可能全叫“Vehicle”。

       對象連名都沒有,沒法直接訪問它。我們只能通過對象引用來間接訪問對象。

       為了形象地說明對象、引用及它們之間的關系,可以做一個或許不很妥當的比喻。對象好比是一只很大的氣球,大到我們抓不住它。引用變量是一根繩, 可以用來系汽球。

       如果只執行了第一條語句,還沒執行第二條,此時創建的引用變量veh1還沒指向任何一個對象,它的值是null。引用變量可以指向某個對象,或者為null。

       它是一根繩,一根還沒有系上任何一個汽球的繩。執行了第二句后,一只新汽球做出來了,并被系在veh1這根繩上。我們抓住這根繩,就等于抓住了那只汽球。

       再來一句:

       Vehicle veh2;

就又做了一根繩,還沒系上汽球。如果再加一句:

       veh2 = veh1;

系上了。這里,發生了復制行為。但是,要說明的是,對象本身并沒有被復制,被復制的只是對象引用。結果是,veh2也指向了veh1所指向的對象。兩根繩系的是同一只汽球。

       如果用下句再創建一個對象:

veh2 = new Vehicle();

則引用變量veh2改指向第二個對象。

       從以上敘述再推演下去,我們可以獲得以下結論:

(1)一個對象引用可以指向0個或1個對象(一根繩子可以不系汽球,也可以系一個汽球);

(2)一個對象可以有N個引用指向它(可以有N條繩子系住一個汽球)。

       如果再來下面語句:

       veh1 = veh2;

按上面的推斷,veh1也指向了第二個對象。這個沒問題。問題是第一個對象呢?沒有一條繩子系住它,它飛了。多數書里說,它被Java的垃圾回收機制回收了。

這不確切。正確地說,它已成為垃圾回收機制的處理對象。至于什么時候真正被回收,那要看垃圾回收機制的心情了。

       由此看來,下面的語句應該不合法吧?至少是沒用的吧?

new Vehicle();

不對。它是合法的,而且可用的。譬如,如果我們僅僅為了打印而生成一個對象,就不需要用引用變量來系住它。最常見的就是打印字符串:

    System.out.println(“I am Java!”);

字符串對象“I am Java!”在打印后即被丟棄。有人把這種對象稱之為臨時對象。

       對象與引用的關系將持續到對象回收。

2)封裝

封裝從字面上來理解就是包裝的意思,專業點就是信息隱藏,是指利用抽象數據類型將數據和基于數據的操作封裝在一起,使其構成一個不可分割的獨立實體,數據被保護在抽象數據類型的內部,盡可能地隱藏內部的細節,只保留一些對外接口使之與外部發生聯系。系統的其他對象只能通過包裹在數據外面的已經授權的操作來與這個封裝的對象進行交流和交互。也就是說用戶是無需知道對象內部的細節(當然也無從知道),但可以通過該對象對外的提供的接口來訪問該對象。

       對于封裝而言,一個對象它所封裝的是自己的屬性和方法,所以它是不需要依賴其他對象就可以完成自己的操作。

       使用封裝有三大好處:

          1、良好的封裝能夠減少耦合。

          2、類內部的結構可以自由修改。

          3、可以對成員進行更精確的控制。

          4、隱藏信息,實現細節。

現在我們從程序的角度來分析封裝帶來的好處。如果我們不使用封裝(該對象就沒有setter()和getter()),那么Husband類應該這樣寫:

public class Husband {      public String name ;      public String sex ;      public int age ;      public Wife wife;}   

       我們應該這樣來使用它:

Husband husband = new Husband();  husband.age = 30;  husband.name = "張三";  husband.sex = "男";    //貌似有點兒多余  

       但是那天如果我們需要修改Husband,例如將age修改為String類型的呢?你只有一處使用了這個類還好,如果你有幾十個甚至上百個這樣地方,你是不是要改到崩潰。如果使用了封裝,我們完全可以不需要做任何修改,只需要稍微改變下Husband類的setAge()方法即可。

public class Husband {            /*      * 對屬性的封裝      * 一個人的姓名、性別、年齡、妻子都是這個人的私有屬性      */      private String name ;      private String sex ;      private String age ;    /* 改成 String類型的*/      private Wife wife;            public String getAge() {          return age;      }            public void setAge(int age) {          //轉換即可          this.age = String.valueOf(age);      }            /** 省略其他屬性的setter、getter **/

       其他的地方依然那樣引用(husband.setAge(22))保持不變。

       到了這里我們確實可以看出:封裝確實可以使我們容易地修改類的內部實現,而無需修改使用了該類的客戶代碼。

      我們再看另一個好處:可以對成員變量進行更精確的控制。

      還是那個Husband,一般來說我們在引用這個對象的時候是不容易出錯的,但是有時你迷糊了,寫成了這樣:

Husband husband = new Husband();  husband.age = 300;  

      也許你是因為粗心寫成了,你發現了還好,如果沒有發現那就麻煩大了,逼近誰見過300歲的老妖怪??!

  但是使用封裝我們就可以避免這個問題,我們對age的訪問入口做一些控制(setter)如:

public class Husband {            /*      * 對屬性的封裝      * 一個人的姓名、性別、年齡、妻子都是這個人的私有屬性      */      private String name ;      private String sex ;      private int age ;    /* 改成 String類型的*/      private Wife wife;        public int getAge() {          return age;      }        public void setAge(int age) {          if(age > 120){              System.out.println("ERROR:error age input....");    //提示錯誤信息          }else{              this.age = age;          }                }            /** 省略其他屬性的setter、getter **/        }  

      上面都是對setter方法的控制,其實通過使用封裝我們也能夠對對象的出口做出很好的控制。例如性別我們在數據庫中一般都是已1、0方式來存儲的,但是在前臺我們又不能展示1、0,這里我們只需要在getter()方法里面做一些轉換即可。

public String getSexName() {          if("0".equals(sex)){              sexName = "女";          }          else if("1".equals(sex)){              sexName = "男";          }          else{              sexName = "人妖???";          }          return sexName;      }  

       在使用的時候我們只需要使用sexName即可實現正確的性別顯示。同理也可以用于針對不同的狀態做出不同的操作。

public String getCzHTML(){          if("1".equals(zt)){              czHTML = "<a href='javascr;          } else{              czHTML = "<a href='Javascript:void(0)' onclick='jy("+id+")'>禁用</a>";          }          return czHTML;      }  

3)繼承

我們可以把JAVA中的類分為以下三種:

類:使用class定義且不含有抽象方法的類。

抽象類:使用abstract class定義的類,它可以含有,也可以不含有抽象方法。

接口:使用interface定義的類。

在這三種類型之間存在下面的繼承規律:

類可以繼承(extends)類,可以繼承(extends)抽象類,可以繼承(implements)接口。

抽象類可以繼承(extends)類,可以繼承(extends)抽象類,可以繼承(implements)接口。

接口只能繼承(extends)接口。

繼承是使用已存在的類的定義作為基礎建立新類的技術,新類的定義可以增加新的數據或新的功能,也可以用父類的功能,但不能選擇性地繼承父類。這種技術使得復用以前的代碼非常容易,能夠大大縮短開發周期,降低開發費用。

繼承是為了重用父類代碼,同時為實現多態性作準備。

繼承是所有OOP語言不可缺少的部分,在java中使用extends關鍵字來表示繼承關系。當創建一個類時,總是在繼承,如果沒有明確指出要繼承的類,就總是隱式地從根類Object進行繼承。比如下面這段代碼:

class Person {    public Person() {             }} class Man extends Person {    public Man() {             }}

類Man繼承于Person類,這樣一來的話,Person類稱為父類(基類),Man類稱為子類(導出類)。如果兩個類存在繼承關系,則子類會自動繼承父類的方法和變量,在子類中可以調用父類的方法和變量。在java中,只允許單繼承,也就是說 一個類最多只能顯示地繼承于一個父類。但是一個類卻可以被多個類繼承,也就是說一個類可以擁有多個子類。

  1.子類繼承父類的成員變量

  當子類繼承了某個類之后,便可以使用父類中的成員變量,但是并不是完全繼承父類的所有成員變量。具體的原則如下:

  1)能夠繼承父類的public和protected成員變量;不能夠繼承父類的private成員變量;

  2)對于父類的包訪問權限成員變量,如果子類和父類在同一個包下,則子類能夠繼承;否則,子類不能夠繼承;

  3)對于子類可以繼承的父類成員變量,如果在子類中出現了同名稱的成員變量,則會發生隱藏現象,即子類的成員變量會屏蔽掉父類的同名成員變量。如果要在子類中訪問父類中同名成員變量,需要使用super關鍵字來進行引用。

  2.子類繼承父類的方法

  同樣地,子類也并不是完全繼承父類的所有方法。

  1)能夠繼承父類的public和protected成員方法;不能夠繼承父類的private成員方法;

  2)對于父類的包訪問權限成員方法,如果子類和父類在同一個包下,則子類能夠繼承;否則,子類不能夠繼承;

  3)對于子類可以繼承的父類成員方法,如果在子類中出現了同名稱的成員方法,則稱為覆蓋,即子類的成員方法會覆蓋掉父類的同名成員方法。如果要在子類中訪問父類中同名成員方法,需要使用super關鍵字來進行引用。

  注意:隱藏和覆蓋是不同的。隱藏是針對成員變量和靜態方法的,而覆蓋是針對普通方法的。(后面會講到)

  3.構造器

  子類是不能夠繼承父類的構造器,但是要注意的是,如果父類的構造器都是帶有參數的,則必須在子類的構造器中顯示地通過super關鍵字調用父類的構造器并配以適當的參數列表。如果父類有無參構造器,則在子類的構造器中用super關鍵字調用父類構造器不是必須的,如果沒有使用super關鍵字,系統會自動調用父類的無參構造器??聪旅孢@個例子就清楚了:

class Shape {         protected String name;         public Shape(){        name = "shape";    }         public Shape(String name) {        this.name = name;    }} class Circle extends Shape {         private double radius;         public Circle() {        radius = 0;    }         public Circle(double radius) {        this.radius = radius;    }         public Circle(double radius,String name) {        this.radius = radius;        this.name = name;    }}

這樣的代碼是沒有問題的,如果把父類的無參構造器去掉,則下面的代碼必然會出錯:

 

改成下面這樣就行了:

 

  4.super

  super主要有兩種用法:

  1)super.成員變量/super.成員方法;

  2)super(parameter1,parameter2....)

  第一種用法主要用來在子類中調用父類的同名成員變量或者方法;第二種主要用在子類的構造器中顯示地調用父類的構造器,要注意的是,如果是用在子類構造器中,則必須是子類構造器的第一個語句。

4)多態

     方法的重寫、重載與動態連接構成多態性。Java之所以引入多態的概念,原因之一是它在類的繼承問題上和C++不同,后者允許多繼承,這確實給其帶來的非常強大的功能,但是復雜的繼承關系也給C++開發者帶來了更大的麻煩,為了規避風險,Java只允許單繼承,派生類與基類間有IS-A的關 系(即“貓”is a “動物”)。這樣做雖然保證了繼承關系的簡單明了,但是勢必在功能上有很大的限制,所以,Java引入了多態性的概念以彌補這點的不足,此外,抽象類和接口也是解決單繼承規定限制的重要手段。同時,多態也是面向對象編程的精髓所在。
     多態又分為設計時多態和運行時多態,例如重載又被稱為設計時多態,而對于覆蓋或繼承的方法,JAVA運行時系統根據調用該方法的實例的類型來決定選擇調用哪個方法則被稱為運行時多態。總而言之,面向對象的設計的典型特點就是繼承,封裝和多態,這些特點也是面向對象之所以能如此盛行的關鍵所在。

對于多態,可以總結它為:

    一、使用父類類型的引用指向子類的對象;該引用只能調用父類中定義的方法和變量;

    二、如果子類中重寫了父類中的一個方法,那么在調用這個方法的時候,將會調用子類中的這個方法;(動態連接、動態調用)

    三、變量不能被重寫(覆蓋),重寫的概念只針對方法。

重寫,英文名是overriding,是指在繼承情況下,子類中定義了與其基類中方法具有相同型構的新方法,就叫做子類把基類的方法重寫了。這是實現多態必須的步驟。

重載,英文名是overloading,是指在同一個類中定義了一個以上具有相同名稱,但是型構不同的方法。在同一個類中,是不允許定義多于一個的具有相同型構的方法的。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品网红直播| 91免费看国产| 这里只有精品视频| 青草青草久热精品视频在线观看| 亚洲a在线观看| 一区二区三区四区视频| 亚洲影视九九影院在线观看| 亚洲免费影视第一页| 91人人爽人人爽人人精88v| 国产精品一久久香蕉国产线看观看| 性色av一区二区三区红粉影视| 亚洲精品一区二区三区婷婷月| 国产精品第一视频| 亚洲欧美在线免费| 亚洲天堂网在线观看| 国产精品一二三在线| 欧日韩不卡在线视频| 欧美伦理91i| 国产主播喷水一区二区| 成人淫片在线看| 色综合五月天导航| 在线看日韩av| 欧美激情视频一区二区三区不卡| 亚洲aⅴ日韩av电影在线观看| 97国产精品视频人人做人人爱| 国产成人精品一区| 97视频在线观看免费高清完整版在线观看| 国产一区二区三区欧美| 国产精品第一页在线| 国产欧美一区二区三区四区| 久久久久久97| 欧美日韩中国免费专区在线看| 久久精品亚洲94久久精品| 久久久国产在线视频| 欧美成人午夜剧场免费观看| 茄子视频成人在线| 日韩在线视频中文字幕| 影音先锋欧美在线资源| 欧美日韩亚洲91| 欧美成人中文字幕在线| 992tv在线成人免费观看| 亚洲国产精品福利| 欧美精品videosex性欧美| 九九久久久久久久久激情| 亚洲色图五月天| 欧美激情亚洲精品| 尤物九九久久国产精品的分类| 日韩在线视频中文字幕| 国产精品久在线观看| 日韩激情片免费| 亚洲国产高清高潮精品美女| 国产精品自产拍在线观看中文| 97国产精品久久| 尤物99国产成人精品视频| 91精品国产高清久久久久久91| 国产精品劲爆视频| 久久久久久网站| 色综合伊人色综合网| 国产精品一区二区三区久久| 国产深夜精品福利| 91免费在线视频| 欧美电影在线观看高清| 亚洲欧美在线免费观看| 日韩女在线观看| 欧美激情亚洲激情| 欧美日韩中国免费专区在线看| 久久97精品久久久久久久不卡| 国产精品福利在线观看网址| 国产亚洲精品久久久| 麻豆精品精华液| 91欧美视频网站| 一本一道久久a久久精品逆3p| 国产拍精品一二三| 55夜色66夜色国产精品视频| 欧美性高潮床叫视频| 国产成人精品一区二区在线| 亚洲国产成人精品久久久国产成人一区| 国产在线98福利播放视频| 2021久久精品国产99国产精品| 奇米成人av国产一区二区三区| 亚洲天堂av在线播放| 欧美亚洲国产成人精品| 国产精品久久综合av爱欲tv| 精品久久国产精品| 韩国视频理论视频久久| 久久久国产在线视频| 亚洲精品美女在线观看| 欧美亚州一区二区三区| 91日韩在线播放| 久久成人精品视频| 欧美精品aaa| 国产精品美女www| 姬川优奈aav一区二区| 高清欧美电影在线| 国产69精品99久久久久久宅男| 久久久久久亚洲精品不卡| 亚洲性视频网站| 成人激情黄色网| 九九热99久久久国产盗摄| 国产精品国语对白| 欧美日韩性生活视频| 国产精品视频色| 欧美大片免费观看在线观看网站推荐| 精品国产网站地址| 国产在线观看一区二区三区| 日韩欧美在线字幕| 麻豆乱码国产一区二区三区| 国产精品三级久久久久久电影| 高跟丝袜欧美一区| 亚洲精品午夜精品| 国产精品久久久久久久久久久久| 亚洲视频免费一区| 国产一区二区三区精品久久久| 欧美日韩国产麻豆| 欧美性在线视频| 97精品伊人久久久大香线蕉| 国产美女直播视频一区| 91国内揄拍国内精品对白| 久久久国产一区| 午夜精品久久久久久久久久久久久| 亚洲国产欧美自拍| 91亚洲精品一区| 国产精品欧美日韩一区二区| 久久久久久综合网天天| 狠狠色狠色综合曰曰| 亚洲欧洲在线观看| 亚洲精品欧美日韩专区| 国产日产欧美精品| 中文字幕在线亚洲| 国产日韩精品在线| 伊人青青综合网站| 欧美黑人巨大精品一区二区| 综合欧美国产视频二区| 在线视频日韩精品| 日韩欧美在线国产| 亚州国产精品久久久| 日韩中文字幕第一页| 久久成人国产精品| 日韩欧美aⅴ综合网站发布| 久久精品国产成人精品| 欧美精品久久久久| 日韩av免费在线播放| 欧美视频在线免费看| 日韩经典中文字幕| 亚洲free嫩bbb| 欧美噜噜久久久xxx| 国产精品入口夜色视频大尺度| 97在线视频免费观看| 91大神在线播放精品| 91干在线观看| 亚洲一区亚洲二区| 在线观看日韩视频| 亚洲欧洲黄色网| 日韩av在线精品| 欧美日韩国产黄| 欧美国产日韩一区| 亚洲性生活视频| 38少妇精品导航| 国产欧美精品日韩| 中文字幕亚洲情99在线| 国产成人自拍视频在线观看| 国产在线拍偷自揄拍精品| 精品中文字幕视频| 欧美成年人网站|