面向物件基礎學習心得
一、類與物件
類是用來對一組具有相同特性事物的描述,而物件就是類的例項,類用來描述物件,就像一座大樓與樓的設計圖的關係,蓋成一座大樓需要一張設計圖來確定這座樓有多高,有多大,一層有幾個房間等。萬物皆物件。
例如:
//一個描述人的類
public class Person {
private String name; //人的姓名
private int age; //人的年齡
private String sex ; //人的性別
public void spaek() {
System.out.println("說話");
}
}
上面的程式碼,是一個關於人的類, 類中描述了一個人的屬性如姓名,年齡;還有人的一個動作說話,可以說,通過這個類,我們就能簡單的得到一個‘人’。
Person people1 = new Person(); //java中通過new關鍵字可以建立一個物件。
people1.speak(); // 通過物件可以呼叫該物件的speak方法。
建立一個物件後就可以呼叫其中的成員變數和方法,要注意成員變數的修飾符,public(在所有的類中都能訪問),private(只能在自身類中訪問,也不能在子類中訪問),protected(只能被自身類,子類和同一包中的類訪問),一般常用的就這三個。在上述程式碼中,呼叫了speak方法,其修飾符public,說明可以任意類中的訪問,而name,age屬性,都是私有的private,只能在本類中訪問,如果需要訪問,我們可以在Person類設定return方法來返回,這樣可以保護類中的資料,起到封裝的特性,如:
public String getName(){
return this.name;
}
二、構造方法
構造方法就是對物件的初始化,就是在new物件時,使物件當出現時就自帶有一些屬性值,比如說一個人,剛出生是父母一般都會起好名字,那麼我們為什麼不在建立物件時就給對像的名字賦值呢?這就需要構造方法。
public class Person {
private String name;
protected int age;
//構造方法,需要傳入名字。
public Person(String name) {
this.name = name;
}
public void spaek() {
System.out.println("說話");
}
public String getName(){
return this.name;
}
}
構造方法是與類同名,公共的,沒有返回值的方法,不用使用者呼叫,會在建立物件是自動呼叫。
Person people1 = new Person("小王");
people1.getName(); //呼叫people1的getName方法得到name的值 此時name的值同過構造方法的賦值,為“小王”。
三、 重構
上面我們講解了構造方法,那麼問題來了,如果一個人一出生還沒有起好名字,那怎麼辦呢?這就需要說到方法的重構了。就是方法名稱一樣,返回值一樣,就是方法的傳參不一樣。建立物件是根據傳入引數的個數。型別的不同,來呼叫不同的構造方法。不止是構造方法,成員方法也能重構(注意:重構時的引數要麼要在個數上不同,要麼要在傳入引數的型別上不同)。
public class Person {
private String name;
protected int age;
public Person() { //沒有引數的構造方法
this.name = "無名";
}
public Person(String name) {
this.name = name;
}
public void spaek() {
System.out.println("說話");
}
public String getName(){
return this.name;
}
}
當我們呼叫時,可以傳入不同的引數來建立物件。
Person people1 = new Person("小王"); //建立一個名字為小王的人,呼叫有參構造方法。
Person people2 = new Person(); //建立一個沒有名稱的人,呼叫無參構造方法
System.out.println(people1.getName()); // 輸出為 小王
System.out.println(people2.getName() //輸出為 無名
四、封裝
封裝、繼承、多型是面向物件的三大特性,現在我們來說封裝, 封裝就是每個物件都包含他能進行操作所需要的所有資訊,把這些資訊包裝在類中,這樣就實現了封裝。
封裝有很多好處,第一、良好的封裝能夠減少耦合,第二、類內部的實現可以自由的修改。
類的封裝就好比一座房子,裡面擺放了精美的傢俱,如果沒有圍牆,那房子內的物品任何人都可以看或者改動,由於有了圍牆(封裝),房屋內的物品就不會被外人動了,但是如果沒有門窗,那麼房子就成了一個鐵盒子,就算裡面的東西再怎麼豪華,再怎麼精美,人不能住進去,也沒用。所以要有門窗,使主人能夠住進來。就像剛才的那個Person類,其中的name屬性是私有的,不能夠在類外訪問,我們加了個getName()方法,是我們能夠訪問到name 的值,這就是封裝物件暴露在外的屬性和方法。
五、繼承
繼承就是子類繼承父類 ,會繼承父類的非private的成員變數和成員方法,子類也能擁有屬於自及的成員變數和成員方法,並且能夠重寫父類的成員方法。
例如:人是一種總稱,但是人有分為中國人,美國人,德國人等,各個不同國家的人擁有相同的屬性,如姓名,性別,年齡等,那麼我們可以使各個國家人的類繼承人的類,人類中包括姓名、性別、年齡等一些共有屬性。而各個國家的人類中可以有一些輸入自己的一些行屬性等。
class Person {
public String name;
public int age;
public Person() {
this.name = "無名";
}
public Person(String name) {
this.name = name;
}
public void spaek() {
System.out.println("說話");
}
public void run () {
System.out.println("跑");
}
}
//繼承父類
class Chinese extends Person {
//構造方法,super()呼叫父類的方法
public Chinese(String name) {
super(name);
}
//子類特有的方法,中國人唱豫劇
public void sing() {
System.out.println("豫劇");
}
}
在上述程式碼中,有Chinese子類繼承了Person父類,(需要說明的是,在子類中的構造方法,如果父類中有構造方法的重構,而父類中沒有無引數的構造方法的宣告,那麼在子類中的構造方法必須指定呼叫那個父類的構造方法,否則,將會出錯。)會擁有父類的所有成員和方法,而在子類中則增加類中國人特有的京劇。如果我們在main函式中new出Chinese的物件,那麼是可以呼叫父類的成員屬性和方法的。
如果之後我們想加入美國人、德國人等,只需要建立相應的類,然後繼承Person類,同樣可以擁有name,age等屬性,以此,提高了程式碼的可讀性、和複用性。
使用繼承是需要注意的是,兩事物A和B之間的關係必須是A包含B,那麼才能讓B繼承A。
六、多型
現在假設要舉行一場跑步運動會。各個國家的熱都要參加,要怎樣才能讓不同國家的人同時賽跑呢,那麼這就用到了多型,多型就是不同的對像可以執行相同的動作,就拿豫劇來說吧,有一位非常出名的老父親,演豫劇演的特別好,他兒子每天跟老父親學習,也學是非常像,有一天,老父親生病了,上不了臺表演,他兒子可以替父親上臺表演,因為他們表演的特別像,再因為在臺上化了妝,觀眾根本認不出來。這就是多型的原理,宣告對像是宣告父類物件,new物件時new出子類物件。
class Person {
public String name;
public int age;
public Person() {
this.name = "無名";
}
public Person(String name) {
this.name = name;
}
public void spaek() {
System.out.println("說話");
}
public void run () {
System.out.println("跑");
}
}
class Chinese extends Person {
public Chinese(String name) {
super(name);
}
public void run(){
System.out.println("我是中國人"+this.name+",我參加運動會");
}
public void sing() {
System.out.println("豫劇");
}
}
public class RunSport {
public static void main(String[] args) {
Person chinese = new Chinese("小王"); //用父類指向子類物件。
chinese.run(); // 呼叫子類中重寫後的run方法 ,輸出 "我是中國人小王,我參加運動會"
}
}
使用多型時要注意 1.子類以父類的身份出現,2. 子類的工作方式以自己的工作方式實現;3. 子類以父類的身份出現時,子類特有的屬性和方法不可以使用(子類中重寫父類的方法可以使用);
下面,我們來運用多型來實現運動會。我們先來增加幾個國家:
//美國人
class American extends Person {
public American(String name) {
super(name);
}
public void run(){
System.out.println("我是美國人"+this.name+",我參加運動會");
}
}
//德國人
class German extends Person {
public German(String name) {
super(name);
}
public void run(){
System.out.println("我是德國人"+this.name+",我參加運動會");
}
}
俄羅斯人
class Russians extends Person {
public Russians(String name) {
super(name);
}
public void run(){
System.out.println("我是俄羅斯人"+this.name+",我參加運動會");
}
}
我們用Java中的容器來儲存參賽人員,來實現比賽。
public class RunSport {
public static void main(String[] args) {
ArrayList<Person> athletes = new ArrayList<Person>();
athletes.add (new Chinese("小王"));
athletes.add (new American("邁克"));
athletes.add (new German("約翰"));
athletes.add (new Russians("鮑里斯"));
for (int i = 0; i < athletes.size(); i++) {
athletes.get(i).run();
}
}
}
/* 執行結果
我是中國人小王,我參加運動會
我是美國人邁克,我參加運動會
我是德國人約翰,我參加運動會
我是俄羅斯人鮑里斯,我參加運動會
*/
這就是不同的物件可以執行相同的動作,但要通過他們自己的程式碼實現來執行。
七、抽象類
在上述代發中我們可以發現Person類根本不用例項化,那麼我們就可以把他設為抽象類,抽象類是不能例項化的。把需要重寫的方法設定為抽象方法。
abstract class Person {
public String name;
public int age;
public Person() {
this.name = "無名";
}
public Person(String name) {
this.name = name;
}
//普通方法,可以被繼承,也可被重寫
public void spaek() {
System.out.println("說話");
}
//抽象方法,在子類中必須重寫
public abstract void run ();
}
class Chinese extends Person {
public Chinese(String name) {
super(name);
}
//重寫父類的抽象方法,以自己的方式實現
public void run(){
System.out.println("我是中國人"+this.name+",我參加運動會");
}
}
抽象方法在使用時應該注意:
- 抽象類不能例項化
- 抽象方法是必須被子類重寫的方法
- 如果父類中擁有抽象方法,那麼父類必須被宣告稱抽象類
八、介面
根據上述例子,當一個國家或幾個國家的人擁有特別的功能時怎麼辦呢,有人會說再各自國家的子類中定義各自特殊的方法,但是那樣的話會使程式碼變得雜亂,使用介面是讓使用者和其他開發人員更容易理解他人的程式碼。
接下來我們以我們的國球為例,假設一個人會打乒乓球,那麼我們先要有一個打乒乓球的介面,宣告介面是需要注意,介面中不允許出現任何成員的執行方式,不能宣告無值得成員變數,若定義成員變數是賦初值,那麼這個成員變數會預設宣告為public static final 型別。
interface PingPong{
//宣告打乒乓球方法
public void play();
}
那麼在子類中就需要實現該方法
class Chinese extends Person implements PingPong{
public Chinese(String name) {
super(name);
}
public void run(){
System.out.println("我是中國人"+this.name+",我參加運動會");
}
public void sing() {
System.out.println("豫劇");
}
//實現介面中方法
public void play() {
System.out.println("打乒乓球");
}
}
有了這個介面,當在出先一個人會打乒乓球時,我們直接讓這個人繼承PingPong類就行了。
現在來說一下介面和抽象類的區別,抽象類可以給出一些成員變數的實現,而介面不能包含有實現,抽象類的抽象成員可被子類部分實現,介面的成員需要需要實現類完全實現。
參考文獻《大話設計模式》程傑著