天天看點

實驗 3 面向對象程式設計練習

一、實驗目的

通過程式設計和上機實驗了解 Java 語言是如何展現面向對象程式設計基本思想,了解類的封裝方法,以及 如何建立類和對象,了解成員變量和成員方法的特性,掌握 OOP 方式進行程式設計的方法,了解類的繼承性和多态性的作用。

二、實驗要求

1. 編寫一個展現面向對象思想的程式。

2. 編寫一個建立對象和使用對象的方法的程式。

3. 編寫一個顯示目前日期和時間的程式。

4. 編寫不同成員變量修飾方法的程式。

5. 編寫不同成員方法修飾方法的程式。

6. 編寫展現類的繼承性(成員變量、成員方法、成員變量隐藏)的程式。

7. 編寫展現類的多态性(成員方法重載、構造方法重載)的程式。

三、實驗内容

(一)建立 Applet 應用小程式

1.建立一個 Applet 應用程式 KY3_1.java 檔案。

(1)程式功能:建立一個 Applet 小程式,使其可以進行簡單的加法運算。該程式要包含類、接口、屬性、方法、事件等面向對象的基本元素。

(2)程式源代碼如下。

import java.awt.*;

import java.awt.event.*;

import java.applet.Applet;

public class KY3_1 extends Applet implements ActionListener {

Label label1=new Label("+");

Label label2=new Label("=");

TextField field1=new TextField(6);

TextField field2=new TextField(6);

TextField field3=new TextField(6);

Button button1=new Button("相加");

public void init() { // 初始化

add(field1);

add(label1);

add(field2);

add(label2);

add(field3);

add(button1);

button1.addActionListener(this);

}

public void actionPerformed(ActionEvent e) { // 處理按鈕事件

int x=Integer.parseInt(field1.getText())+Integer.parseInt(field2.getText());

field3.setText(Integer.toString(x)); // 數值轉換為字元串

}

}

2. 編寫一個浏覽 Applet 應用程式的頁面檔案 KY3_1.HTML,源代碼如。

<html>

<applet code="KY3_1.class" height=200 width=400>

</applet>

</html>

3. 将 KY3_1.java 源程式編譯為 KY3_1.class 檔案

4. 使用浏覽器或使用小程式檢視器浏覽 KY3_1.HTML 檔案(即在指令提示符視窗輸入:

appletviewer KY3_1.HTML),運作。

(二)建立對象并使用對象

1.編寫 Applet 程式

• 程式功能:這個 Applet 程式要在頁面上輸出兩個矩形,并伴有文字輸出。

• KY3_2.java 程式的源代碼如下。

import java.awt.*;

import java.applet.Applet;

public class KY3_2 extends Applet {

MyBox b1=new MyBox();//建立對象 b1

MyBox b2=new MyBox(170,20,60,60); //建立對象 b2

public void paint(Graphics g) {

b1.setPosition(20,20);

b1.setSize(60,60);

b1.draw(g);

g.drawString("矩形 1 的 X 位置: "+b1.getX(), 20, 100);

g.drawString("矩形 1 的 Y 位置: "+b1.getY(), 20, 120);

b2.draw(g);

g.drawString("矩形 2 的 X 位置: "+b2.getX(), b2.getX(), b2.getY()+80);

g.drawString("矩形 2 的 Y 位置: "+b2.getY(), b2.getX(), b2.getY()+100);

}

}

class MyBox {

private int x, y, width, height;

MyBox() {

x=0;

y=0;

width=0;

height=0;

}

MyBox(int xPos, int yPos, int w, int h) {

x=xPos;

y=yPos;

width=w;

height=h;

}

public void setPosition (int xPos, int yPos) {

x=xPos;

y=yPos;

}

public void setSize (int w, int h) {

width=w;

height=h;

}

public int getX() {

return x;

}

public int getY() {

return y;

}

public void draw(Graphics g) {

g.drawRect(x, y, width, height);

}

}

2.編寫一個浏覽 Applet 應用程式的頁面檔案 KY3_2.HTML

<html>

<applet code=" KY3_2.class" height=200 width=400>

</applet>

</html>

3. 将 KY3_2.java 源程式編譯為 KY3_2.class 檔案

4. 使用浏覽器或使用小程式檢視器浏覽KY3_2.HTML檔案(即在指令提示符下輸入:appletviewer

KY3_2.HTML),運作.

思考:程式的結構。類與對象的關系。對象建立、使用、銷毀的過程。

(三)編寫顯示目前日期和時間的程式

1. 編寫Applet 類檔案KY3_3.java

• 程式功能:該程式通過使用一個自定義類Time,實作顯示目前日期和時間的功能

• KY3_3.java 程式源代碼如下。

import java.awt.Graphics;

import java.applet.Applet;

import java.util.Calendar;

class Time {

private Calendar t;

private int y, m, d, hh, mm, ss;

Time (){

t=Calendar.getInstance();

y=t.get(t.YEAR);

m=t.get(t.MONTH)+1;

d=t.get(t.DATE);

hh=t.get(t.HOUR_OF_DAY);

mm=t.get(t.MINUTE);

ss=t.get(t.SECOND);

}

public String getDate() {

return y+" 年"+m+"月"+d+"日";

}

public String getTime() {

String s=hh+" 時"+mm+"分"+ss+"秒";

return s;

}

}

public class KY3_3 extends Applet {

Time t=new Time();

public void paint(Graphics g) {

g.drawString("目前日期:"+t.getDate(),50,40);

g.drawString("目前時間:"+t.getTime(),50,80);

}

}

2. 編寫浏覽KY3_3 類的頁面檔案KY3_3.html

<html>

<applet codebase=e:/java/程式 code=KY3_3.class width=300 height=120>

</applet >

</html>

3. 在浏覽器中浏覽程式運作結果。

(四)使用修飾符

有時需要公開一些變量和方法,有時需要禁止其他對象使用變量和方法,這時可以使用修飾符來實作這個目的。常用的修飾符如下。Public,private,protected,package,static,final,transient,volatile

1. 程式功能:通過兩個類StaticDemo、KY3_4 說明靜态變量/方法與執行個體變量/方法的差別。

2. 編寫類檔案KY3_4.java,程式源代碼如下。

class StaticDemo {

static int x;

int y;

public static int getX() {

return x;

}

public static void setX(int newX) {

x = newX;

}

public int getY() {

return y;

}

public void setY(int newY) {

y = newY;

}

}

public class KY3_4 {

public static void main(String[] args) {

System.out.println("靜态變量x="+StaticDemo.getX());

System.out.println("執行個體變量y="+StaticDemo.getY()); // 非法,編譯時将出錯

StaticDemo a= new StaticDemo();

StaticDemo b= new StaticDemo();

a.setX(1);

a.setY(2);

b.setX(3);

b.setY(4);

System.out.println("靜态變量a.x="+a.getX());

System.out.println("執行個體變量a.y="+a.getY());

System.out.println("靜态變量b.x="+b.getX());

System.out.println("執行個體變量b.y="+b.getY());

}

}

3. 對上面的源程式進行編譯,排錯并運作

(五)方法中參數傳遞的練習

1. 編寫一個傳值調用的程式檔案KY3_5.java。

• 程式功能:程式首先給整型變量x 和y 賦一個初值10,然後使用傳值調用方式調用方法ff1對x 和y 做乘方及輸出x 和y 的乘方值,最後再輸出x 和y 的乘方值。

• 程式源代碼如下。

class KY3_5 {

public static void main(String[] args) {

int x=10, y=10;

ff1(x, y);

System.out.println("x="+x+", y="+y);

}

static void ff1(int passX, int passY) {

passX=passX*passX;

passY=passY*passY;

System.out.println("passX="+passX+", passY="+passY);

}

}

• 編譯KY3_5.java

• 分析其運作結果

2. 編寫一個調用對象方法的程式檔案KY3_6.java。

• 程式功能:通過調用對象的方法在方法調用後修改了成員變量的值。

• KY3_6.java 程式源代碼如下。

class KY3_6 {

public static void main(String[] args) {

Power p=new Power();

p.ff2(10,10);

System.out.println("方法調用後 x="+p.x+", y="+p.y);

}

}

class Power{

int x=10, y=10;

void ff2(int passX, int passY) {

System.out.println("初始時 x="+x+", y="+y);

x=passX*passX;

y=passY*passY;

System.out.println("方法調用中 x="+x+", y="+y);

}

}

• 編譯KY3_6.java

以上兩個實驗例子僅僅是為了說明Java 程式設計中參數傳遞時要注意的問題,在實際程式設計中是不可取的,因為完全可以采用其它更好的方法來實作參數的傳遞。例如,前面還使用過傳遞對象的方式。

思考:方法的參數傳遞有哪些方式?差別時什麼?

(六)類的繼承性練習

1. 進一步了解繼承的含義

新類可從現有的類中産生,并保留現有類的成員變量和方法并可根據需要對它們加以修改。新類 還可添加新的變量和方法。這種現象就稱為類的繼承。

當建立一個新類時,不必寫出全部成員變量和成員方法。隻要簡單地聲明這個類是從一個已定義的類繼承下來的,就可以引用被繼承類的全部成員。被繼承的類稱為父類或超類(superclass),這個新類稱為子類。

Java 提供了一個龐大的類庫讓開發人員繼承和使用。設計這些類是出于公用的目的,是以,很少有某個類恰恰滿足你的需要。你必須設計自己的能處理實際問題的類,如果你設計的這個類僅僅實作了繼承,則和父類毫無兩樣。是以,通常要對子類進行擴充,即添加新的屬性和方法。這使得子類要比父類大,但更具特殊性,代表着一組更具體的對象。繼承的意義就在于此。

2. 建立公共類 KY3_7_P

(1)編寫程式檔案 KY3_7_P.java,源代碼如下。

public class KY3_7_P

{

protected String xm; //具有保護修飾符的成員變量

protected int xh;

void setdata(String m,int h) //設定資料的方法

{

xm =m;

xh = h;

}

public void print() //輸出資料的方法

{

System.out.println(xm+", "+xh);

}

}

(2)編譯 KY3_7_P.java,産生類檔案 KY3_7_P.class。

3.建立繼承的類

(1)程式功能:通過 KY3_7_P 類産生子類 KY3_8,其不僅具有父類的成員變量 xm(姓名)、xh(學号),還定義了新成員變量 xy(學院)、xi(系)。在程式中調用了父類的 print 方法,同時可以看出子類也具有該方法。

(2)編寫 KY3_8.java 程式,源代碼如下。

class KY3_8 extends KY3_7_P

{

protected String xy;

protected String xi;

public static void main(String args[])

{

KY3_7_P p1 = new KY3_7_P();

p1.setdata("帥零",12321) ;

p1.print();

KY3_8 s1 = new KY3_8() ;

s1.setdata("郭麗娜",12345); //調用父類的成員方法

s1.xy="經濟管理學院"; //通路本類的成員變量

s1.xi="資訊管理系"; //通路本類的成員變量

s1.print();

System.out.print(s1.xm+", "+s1.xy+", "+s1.xi);

}

}

(3)編譯并運作程式

注意:公共類 KY3_7_P 與 KY3_8 類要在同一檔案夾(路徑)内。

(七)類的多态性練習

1. 了解類的多态性

類的繼承發生在多個類之間,而類的多态隻發生在同一個類上。在一個類中,可以定義多個同名的方法,隻要确定它們的參數個數和類型不同。這種現象稱為類的多态。

多态使程式簡潔,為程式員帶來很大便利。在OOP 中,當程式要實作多個相近的功能時,就給相應的方法起一個共同的名字,用不同的參數代表不同的功能。這樣,在使用方法時不論傳遞什麼參數,隻要能被程式識别就可以得到确定的結果。

類的多态性展現在方法的重載(overload)上,包括成員方法和構造方法的重載。

2. 方法的重載

方法的重載是指對同名方法的不同使用方式。

• 程式功能:對不同的數進行排序輸出。在IntSort 類中定義3 個同名的方法sort,在

• 編寫KY3_9.java 檔案,源代碼如下。

import java.awt.Graphics;

import java.applet.Applet;

class IntSort {

public String sort(int a, int b) {

if (a>b)

return a+" "+b;

else

return b+" "+a;

}

public String sort(int a, int b, int c) {

int swap;

if (a<b) {

swap=a;

a=b;

b=swap;

}

if (a<c) {

swap=a;

a=c;

c=swap;

}

54

if (b<c) {

swap=b;

b=c;

c=swap;

}

return a+" "+b+" "+c;

}

public String sort(int arr[]) {

String s=" ";

int swap;

for (int i=0; i<arr.length; i++)

for (int j=0; j<arr.length-1; j++)

if (arr[j]>arr[j+1]) {

swap=arr[j];

arr[j]=arr[j+1];

arr[j+1]=swap;

}

for (int i=0; i<arr.length; i++)

s=s+arr[i]+" ";

return s;

}

}

public class KY3_11 extends Applet {

IntSort s=new IntSort();

public void paint(Graphics g) {

int a=30, b=12, c=40;

int arr[]={34,8,12,67,44,98,52,23,16,16};

g.drawString("兩個數的排序結果:"+s.sort(a,b),30,30);

g.drawString("三個數的排序結果:"+s.sort(a,b,c),30,60);

g.drawString("數組的排序結果:"+s.sort(arr),30,90);

}

}

• 編譯并運作程式

• 三個同名方法

public String sort (int a, int b)

public String sort (int a, int b, int c)

public String sort (int arr[])

• 編寫KY3_10 類檔案的頁面檔案KY3_11.html

<html>

<applet codebase=e:/java/程式 code=KY3_11.class width=420 height=380>

</applet >

</html>

3. 構造方法的重載

構造方法的名稱和類同名,沒有傳回類型。盡管構造方法看起來和一般的成員方法沒有差别,但它不是方法,也不是類的成員。是以,構造方法不能直接調用,隻能由new 操作符調用。

構造方法對于類是十分重要的,對象的初始化任務要靠構造方法來完成。重載構造方法的目的是提供多種初始化對象的能力,使程式員可以根據實際需要選用合适的構造方法來初始化對象。

• 編寫構造方法RunDemo 的重載程式檔案KY3_11,源代碼如下。

class RunDemo {

private String userName, password;

56

RunDemo() {

System.out.println("全部為空!");

}

RunDemo(String name) {

userName=name;

}

RunDemo(String name, String pwd) {

this(name);

password=pwd;

check();

}

void check() {

String s=null;

if (userName!=null)

s="使用者名:"+userName;

else

s="使用者名不能為空!";

if (password!="12345678")

s=s+" 密碼無效!";

else

s=s+" 密碼:********";

System.out.println(s);

}

}

public class KY3_12 {

public static void main(String[] args) {

new RunDemo();

new RunDemo("劉新宇");

new RunDemo(null,"邵麗萍");

new RunDemo("張馳","12345678");

}

}

• 編譯并運作程式

• 三個構造方法,其中第一個無參構造方法RunDemo() 的實際作用是對成員變量賦預設初值,由于userName和password都是String 類,是以它們的預設初值為null。第二個構造方法RunDemo(String) 隻有一個參數,用來對成員變量userName 賦初值。第三個構造方法RunDemo(String, String) 有兩個參數,并有更多的内容,首先調用this(name),其實際作用就是調用目前類的構造方法RunDemo(String name);然後對成員變量password 指派;最後調用check 方法來檢查userName 和password,類似于一般程式的密碼驗證。重載構造方法的執行由對象根據實際參數的個數、類型和順序确定。

四、思考題

1. 說明使用變量之前是不是都要先聲明變量。說明使用變量之前是不是都要先指派,為什麼?

2. 說明什麼是構造方法。

3. 說明程式中有多個類時如何确定源程式檔案的名稱。

4. 說明類的繼承和多态有什麼作用,在使用上應該注意什麼問題。