Java【第七篇】面向對象之類設計

Java類的繼承

類繼承語法規則

< 修飾符> class < 子類名稱> [extends < 父類>] 
{
    <屬性和方法的聲明>
} 

類的繼承

子類繼承了父類,就繼承了父類的方法和屬性。
在子類中,可使用父類中定義的方法和屬性,也能夠建立新的數據和方法。
於是,子類一般比父類的功能更多。
在Java中,繼承的關鍵字用的是「extends」,即子類不是父類的子集,而是對父類的「擴展」。java

繼承規則

Java只支持單繼承,不容許多重繼承
一個子類只能有一個父類
一個父類能夠派生出多個子類
子類不能繼承父類中私有的(private)的成員變量和方法app

示例

package com.uncleyong;

import java.util.Date;

public class Person {
    public String name;
    public int age;
    public Date birth;

    private String lover = "lucy";

    public String getInfo(){
        return "name: " + name + ", " +
                "age: " + age + ", " +
                "birth: " + birth+ ", " +
                "lover: " + lover;
    }

}

  

package com.uncleyong;


public class Student extends Person{
    public String school;
}

  

package com.uncleyong;

import java.util.Date;

public class TestPerson {
    public static void main(String[] args) {
    	Student student = new Student();
    	student.name = "Jerry";
    	student.birth = new Date();
    	student.age = 1;
    	student.school = "清華";
		System.out.println(student.getInfo());


        Person person = new Person();
		person.age = 1;
		person.birth = new Date();
		person.name = "Tom";

		System.out.println(person.getInfo());
    }
}  

訪問控制

能夠對Java類中定義的屬性和方法進行訪問控制----規定不一樣的保護等級: public、protected、default、privateide

方法的重寫、覆蓋

在子類中能夠根據須要對從父類中繼承來的方法進行改造—覆蓋方法(方法的重置、重寫),在程序執行時,子類的方法將覆蓋父類的方法。測試

覆蓋方法必須和被覆蓋方法具備相同的方法名稱、參數列表和返回值類型。this

覆蓋方法不能使用比被覆蓋方法更嚴格的訪問權限。spa

示例

package com.uncleyong;

/**
 * 定義一個ManKind類,包括
 * 成員變量 int sex 和 int salary;
 * 方法 void manOrWorman():根據sex的值顯示「man」(sex==1)或者「women」(sex==0);
 * 方法 void employeed():根據salary的值顯示「no job」(salary==0)或者「 job」(salary!=0)。
 */
public class ManKind {

    int sex;
    int salary;

    public void manOrWoman(){
        if(sex == 0){
            System.out.println("woman");
        }else if(sex == 1){
            System.out.println("man");
        }
    }

    public void employeed(){
        if(salary != 0){
            System.out.println("job");
        }else{
            System.out.println("no job");
        }
    }

}

  

package com.uncleyong;

/**
 * 定義類 Kids1 繼承ManKind,幷包括
 * 成員變量 int yearsOld;
 * 方法 printAge() 打印 yearsOld 的值。
 *
 * 在Kids1中從新定義employed() 方法,覆蓋父類ManKind中定義的employed()方法,
 * 輸出「Kids should study and no job.」
 */
public class Kids1 extends ManKind {

    int yearsOld;

    void printAge(){
        System.out.println("yearsOld: " + yearsOld);
    }

    // 方法重寫
    public void employeed() {
        System.out.println("Kids should study and no job.");
    }

    //在Kids1類的main方法中實例化Kids1的對象 someKid,用該對象訪問其父類的成員變量及方法。
    public static void main(String[] args) {
        Kids1 someKid = new Kids1();
        someKid.sex = 1;
        someKid.salary = 5000;
        someKid.yearsOld = 25;

        someKid.manOrWoman();
        someKid.employeed();
        someKid.printAge();
    }
}

super 關鍵字

super的功能

在Java類中使用super來引用父類的成分orm

super可用於訪問父類中定義的屬性
super可用於調用父類中定義的成員方法
super可用於在子類構造方法中調用父類的構造方法
super的追溯不只限於直接父類對象

構造方法不能繼承

子類繼承父類全部的成員變量和成員方法,但不繼承父類的構造方法
在一個Java類中能夠經過兩種方式得到構造方法:
  使用系統默認的無參數構造方法
  顯式定義一個或多個構造方法
一旦顯式定義了構造方法,則系統再也不提供默認構造方法blog


調用父類構造方法

在子類的構造方法中可以使用super(參數列表)語句調用父類的構造方法
若是子類的構造方法中沒有顯示地調用父類構造方法,也沒有使用this關鍵字調用重載的其它構造方法,則系統默認調用父類無參數的構造方法
若是子類構造方法中既未顯式調用父類構造方法,而父類中又沒有無參的構造方法,則編譯出錯繼承

示例

package com.uncleyong;

public class Circle {

    protected double radius;

    public Circle() {
        this.radius = 1;
        System.out.println("父類構造方法");
    }

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    public double findArea(){
        return 3.14 * radius * radius;
    }

}

  

package com.uncleyong;

public class Cylinder extends Circle{

    private double length;

    public Cylinder() {
        this.length = 1;
    }

    public double getLength() {
        return length;
    }

    public void setLength(double length) {
        this.length = length;
    }

    /**
     * 返回圓柱的體積
     * @return
     */
    public double findVolume(){
        return super.findArea() * length;  // 這裏要加super表示調父類的,不加super表示調本類中的findArea方法
    }

    /**
     * 返回圓柱的表面積
     */
    @Override
    public double findArea() {
        return super.findArea() * 2 + 2 * 3.14 * radius * length;
    }

}

 

package com.uncleyong;

public class TestCylinder {

    public static void main(String[] args) {

        Cylinder cylinder = new Cylinder();

		cylinder.setLength(2);

        //返回表面積
        System.out.println(cylinder.findArea());
        //返回體積
        System.out.println(cylinder.findVolume());
    }

}

多態性及其應用

多態性

多態—在Java中,子類的對象能夠替代父類的對象使用(父類類型的變量能夠指向子類的對象)
一個變量只能有一種肯定的數據類型
一個引用類型變量可能指向(引用)多種不一樣類型的對象

Person p = new Student();
Object o = new Person();//Object類型的變量o,指向Person類型的對象
o = new Student(); //Object類型的變量o,指向Student類型的對象

一個引用類型變量若是聲明爲父類的類型,但實際引用的是子類對象,那麼該變量就不能再訪問子類中添加的屬性和方法

Student m = new Student();
m.school = 「pku」; //合法,Student類有school成員變量
Person e = new Student(); 
e.school = 「pku」;	//非法,Person類沒有school成員變量 

屬性是在編譯時肯定的,編譯時e爲Person類型,沒有school成員變量,於是編譯錯誤。

虛擬方法調用(Virtual Method Invocation)

正常的方法調用

Person e = new Person();
e.getInfo();
Student e = new Student();
e.getInfo();

虛擬方法調用(多態狀況下)

Person e = new Student();
e.getInfo();	//調用Student類中重寫的getInfo()方法

編譯時類型和運行時類型:編譯時e爲Person類型,而方法的調用是在運行時肯定的,因此調用的是Student類的getInfo()方法。—— 動態綁定

instanceof 操做符

x instanceof A:檢驗x是否爲類A的對象,返回值爲boolean型。
要求x所屬的類與類A必須是子類和父類的關係,不然編譯錯誤。
若是x屬於類A的子類B,x instanceof A值也爲true。

        Boy b = new Boy();
        System.out.println(">>>>>>>>>>>>>>>>");
        // Boy繼承了Student
//        System.out.println(b instanceof Student);  // true;若是Boy沒有繼承Student,報類型不兼容錯誤
        // Boy2繼承了Boy
        System.out.println(b instanceof Boy2); // false,由於b不是Boy2的對象
        System.out.println(b instanceof Boy); // true,由於b是Boy的對象
        // Boy2繼承了Boy
        Boy2 b2 = new Boy2();
        System.out.println(b2 instanceof Boy); // true,由於b2是Boy的對象

對象類型轉換 (Casting )

基本數據類型的Casting

小的數據類型能夠自動轉換成大的數據類型
  如long g=20; double d=12.0f
能夠把大的數據類型強制轉換(casting)成小的數據類型
  如 floate f=(float)12.0 int a=(int)1200L

對Java對象的強制類型轉換稱爲造型

從子類到父類的類型轉換能夠自動進行
從父類到子類的類型轉換必須經過造型(強制類型轉換)實現
無繼承關係的引用類型間的轉換是非法的
在造型前可使用instanceof操做符測試一個對象的類型

示例

package com.uncleyong;

public class Person {
    protected String name="person";
    protected int age=50;
    public String getInfo() {
        return "Name: "+ name + "\n" +"age: "+ age;
    }
}
class Student extends Person {
    protected String school="pku";
    public String getInfo() {
        return  "Name: "+ name + "\nage: "+ age
                + "\nschool: "+ school;
    }

}
class Graduate extends Student{
    public String major="IT";
    public String getInfo()
    {
        return  "Name: "+ name + "\nage: "+ age
                + "\nschool: "+ school+"\nmajor:"+major;
    }
}

 

package com.uncleyong;

public class TestInstance {

	/*
	          在類中定義方法method1(Person e);
		在method1中:
		(1)根據e的類型調用相應類的getInfo()方法。
		(2)根據e的類型執行:
		若是e爲Person類的對象,輸出:「a person」;
		若是e爲Student類的對象,輸出
		「a student」
		「a person 」
		若是e爲Graduate類的對象,輸出:
		「a graduated student」
		「a student」
		「a person」
	 */

    public void method1(Person e){  // 多態的體現,Person類型的形參能夠接收實際Person子類對象
        String info = e.getInfo();  // 動態綁定
        System.out.println(info);

        if(e instanceof Graduate){
            System.out.println("a graduated student");
        }
        if(e instanceof Student){
            System.out.println("a student");
        }
        if(e instanceof Person){
            System.out.print("a person");
        }

        System.out.println("\n");

    }

    public static void main(String[] args) {

        TestInstance ti = new TestInstance();

        Person p1 = new Person();
        ti.method1(p1);

        Person p2 = new Student();
        ti.method1(p2);

        Person p3 = new Graduate();
        ti.method1(p3);



    }

}  

Object 類及其主要方法

Object類

Object類是全部Java類的根父類

若是在類的聲明中未使用extends關鍵字指明其父類,則默認父類爲Object類
public class Person {
...
}
等價於:
public class Person extends Object {
...
}
例:
method(Object obj){…}  // 能夠接收任何類做爲其參數
Object o=new Person;
method(o);

==操做符與equals方法

==操做符

==:引用類型比較引用(是否指向同一個對象);
  Person p1=new Person();

  Person p2=new Person();

  if (p1==p2){…}

基本類型比較值:

  int a=5; if(a==6){…}
用"=="進行比較時,符號兩邊的數據類型必須一致(可自動轉換的基本數據類型除外),不然編譯出錯;

equals()方法

equals()方法是Object類的方法,因爲全部類都繼承Object類,也就繼承了equals()方法。只能比較引用類型,其做用與「==」相同,比較是否指向同一個對象。格式:obj1.equals(obj2)
特例:當用equals()方法進行比較時,對類File、String、Date及封裝類(Wrapper Class)來講,是比較類型及內容而不考慮引用的是不是同一個對象;
緣由:在這些類中覆蓋了equals()方法。

toString 方法

toString()方法在Object類中定義,其返回值是String類型,返回類名和它的引用地址。在進行String與其它類型數據的鏈接操做時,自動調用toString()方法
  Date now=new Date();
  System.out.println(「now=」+now); 至關於 System.out.println(「now=」+now.toString());  // now=Date@122345
能夠根據須要在用戶自定義類型中重寫toString()方法,如String 類重寫了toString()方法,返回字符串的值。
s1=「hello」;
System.out.println(s1);  // 至關於System.out.println(s1.toString());
基本類型數據轉換爲String類型時,調用了對應封裝類的 toString()方法,int a=10; System.out.println(「a=」+a);

示例

package com.uncleyong;

public class GeometricObject {
    protected  String  color;
    protected  double  weight;
}

 

package com.uncleyong;

public class Circle1 extends GeometricObject{
    private double radius;

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    public Circle1() {
        this.radius = 1;
        this.weight = 1;
        this.color = "white";
    }

    public Circle1(double radius) {
        this.radius = radius;
        this.weight = 1;
        this.color = "white";
    }

    public Circle1(double radius, double weight, String color) {
        this.radius = radius;
        this.weight = weight;
        this.color = color;
    }

    public double findArea(){
        return Math.PI * this.radius * this.radius;
    }

    @Override
    public boolean equals(Object obj) {
        if(this == obj){
            return true;
        }

        if(obj == null){
            return false;
        }

        if(!(obj instanceof Circle1)){
            return false;
        }

        Circle1 c = (Circle1) obj;

        return c.getRadius() == this.radius;
    }

    @Override
    public String toString() {
        return "" + this.radius;  // 寫爲return this.radius;不行,由於radius是double
    }
}

  

package com.uncleyong;

public class TestCircle1 {

    /**
     * 寫一個測試類,建立兩個Circle對象,判斷其顏色是否相等;
     * 利用equals方法判斷其半徑是否相等;
     * 利用toString()方法輸出其半徑。
     */
    public static void main(String[] args) {

        Circle1 c1 = new Circle1(1, 2, "Black");
        Circle1 c2 = new Circle1(2, 3, "Black");
        Circle1 c3 = new Circle1(2, 2, "Black");
        Circle1 c4 = new Circle1(2, 3, "Red");

        // 比顏色
        System.out.println(c1.color.equals(c2.color));  // true
        // 比半徑
        System.out.println(c1.equals(c2));  // false

        // 比顏色
        System.out.println(c3.color.equals(c4.color));  // false
        // 比半徑
        System.out.println(c3.equals(c4));  // true

        System.out.println(c1);  // 1.0   打印對象,會自動調對象的toString方法

    }
}

封裝類

針對八種基本定義相應的引用類型—封裝類

int i = 10;
Integer j = 10;  // Integer是封裝類,基本數據類型10賦給j,自動裝箱
相關文章
相關標籤/搜索