บทที่ 9 การพ้องรูป

26
การพองรูป Polymorphism วัตถุประสงค เพื่อใหมีความรูความเขาใจแนวคิดการพองรูป เพื่อใหมีความรูความเขาใจกระบวนการ Overloading เพื่อใหมีความรูความเขาใจกระบวนการ Override เพื่อสามารถนําความรูที่ไดไปเขียนโปรแกรมประยุกตใชกับงานจริงได บทที 9

Upload: -

Post on 17-Aug-2015

42 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: บทที่ 9 การพ้องรูป

การพองรูป Polymorphism

วัตถุประสงค

♦ เพื่อใหมีความรูความเขาใจแนวคิดการพองรูป ♦ เพื่อใหมีความรูความเขาใจกระบวนการ Overloading ♦ เพื่อใหมีความรูความเขาใจกระบวนการ Override ♦ เพื่อสามารถนําความรูท่ีไดไปเขียนโปรแกรมประยุกตใชกับงานจริงได

บทที ่

9

Page 2: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 210

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

เนื้อหาบทเรยีน

♦ การพองรูป(Polymorphism) ♦ การโอเวอรโหลด( Overloading) ♦ การโอเวอรไรด(Overriding) ♦ คียเวิรด final ♦ คลาสนามธรรม(Abstract class) ♦ คียเวิรด Interfaces

Page 3: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 211

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

Polymorphism Polymorphism มาจากภาษากรีกซึ่งหมายความวา หลากหลายรูปแบบ ในการเขียนโปรแกรมเชิง

วัตถุ โพลิมอรฟซึม คือ การที่วัตถุตอบสนองขอความ(message)หนึ่งๆ ในรูปแบบที่แตกตางกันตามแตชนิดของวัตถุนั้นๆ เชน เครื่องเลนเทป เครื่องเลนดีวีด ี ตางตอบสนองตอ การกด Play เหมือนกัน แตรูปแบบการทํางานก็จะแตกตางกันไป

สําหรับในภาษาจาวานั้น คือการที่ Object หนึ่งๆสามารถที่จะถูกอางอิง โดย Object References ตางชนิดกนั แตยังคงสามารถตอบสนองตอ เมธอด ไดเชนเดิม

ตัวอยาง แสดงคลาสที่มีคุณสมบัติโพลิมอรฟซึม การโอเวอรโหลด(Overloading) การกําหนดให เมธอด ซ่ึงอยูใน class เดียวกันมีช่ือเหมอืนกันหรือซํ้ากันไดมากกวาหนึ่ง เมธอด โดยแตละ เมธอด จะตองมี signature(parameter list)ตางกัน แตในสวนของ return type อาจเหมือนหรือตางกันก็ได เพื่อใหคอมไพเลอรสามารถระบุไดวา เมื่อมีการเรียก เมธอด ที่ประโยคหนึ่ง จะให เมธอดใดเปนตัวที่ถูกเรียกกระทํา โดยดูจาก arguments และ returned type ซ่ึงมีลักษณะที่สอดคลองกันกับ เมธอด ณ ตําแหนงทีเ่รียกนั้น เรียกคุณสมบัติดังกลาววาเปนการทํา overload method เพื่อใหเมธอดหรือ

public class VideoPlayer{ void Play() {

System.out.println(“Play Video Tape”); }

} class DVDPlayer extends VideoPlayer {

void Play() { System.out.println(“Play DVD”);

} void Play(String Movie){

System.out.println(“Play ”+Movie); }

}

Page 4: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 212

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

constructor มคีุณสมบัติการพองรูป(Polymorphism) และการที่ method หรือ constructor มีพารามิเตอรที่แตกตางกันนัน้ กลาวไดวา method หรือ constructor เหลานั้นถูก overload ในมุมมองของ Compiler แลว ถือวา Overloading Method ไมมีความเกี่ยวพันใดๆกับ Method เดิมเลย ตัวอยาง แสดงการทํา Overload method

สังเกตวา method static int sq(int n){ /* */} static double sq(float n){ /* */} static double sq(double n){/* */} ทั้งสาม method นี้มีช่ือ method เหมือนกัน แต signature ตางกัน

class Overload{ static int sq(int n) { return n*n ;} /*static double sq(int n) {return (double)n*n;} // error เนื่องจากมี พารามิเตอรเหมือนกับ sq( ) ตัวแรก คอมไพเลอรจะไมสามารถตรวจสอบความถูกตองในการใชงานได*/ static double sq(float n) { return (double)n*n ;}

static double sq (double n) {return (double) n*n ;} public static void main(String args[]){

int x = sq(10); double y = sq(11.0); System.out.println(x); System.out.println(y); }

} ผลลัพธที่ไดจากการรัน 100 121.0

Page 5: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 213

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

ตัวอยาง แสดงการทํา Overload method

ดังนั้นจากทั้งสองตัวอยาง สามารถสรุปไดวา เราสามารถสราง method ที่มีช่ือซํ้ากันไดตราบใด

ที่การสงผานตัวแปรของแตละ methodไมเหมือนกนั ตัวอยางตอไปนี้เปนการโอเวอรโหลดเมทธอด run ที่เปนไปได

void run() { /*……………….. */ } void run(int mile) { /*……………….. */ } void run(long mile) { /*……………….. */ } void run(int mile, boolean x) { /* ……………….. */ } int run(int mile, long mile) { /*……………….. */ } long run(int mile, long mile, boolean x) { /* ……………….. */ }

class Vehicle { int numberOfWheels; boolean hasEngine; void run(int mile){ // (1)

System.out.println(“I am running on the ” + mile + “th mile.” ); } void run(float mile){ // (2)

System.out.println(“I am running on the ” + mile + “th mile.” ); }

} public class DriveACar { public static void main (String[] args) {

Vehicle myCar = new Vehicle(); myCar.run(10); // (3) myCar.run(10.0F); // (4)

} } ผลลัพธที่ไดจากการรัน I am running on the 10th mile. I am running on the 10.0th mile.

Page 6: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 214

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

แตหาม overload method ที่มีตัวแปรสงผานในวงเล็บเหมอืนกัน แตตัวแปรสงกลับตางกัน เพราะคอมไพลเลอรจะแยกความแตกตางไมออกเวลาที่เจอเมธอดนี้ที่อ่ืนในโปรแกรม ตัวอยางตอไปนี้เปนเมธอดสองเมธอดที่อยูรวมกันไมได

void run(int mile) { /*……………….. */ } int run(int x) { /* ……………….. */ } // Error ในกรณีที่ตัวแปรสงผานในเมธอดหนึ่งเปนจํานวนเต็มแบบ int อีกmethodหนึ่งเปนจํานวนเต็ม

แบบ long เวลาเรียกใช เมธอด ตองใส L ตอทายตัวสงผานเสมอเพื่อใหทราบวาเปนการสงตัวแปรแบบ long ดวย มิฉะนั้น Java Virtual Machine จะคิดวาตองการใหเรียก เมธอด ที่มีตัวแปรสงผานแบบ int แมวาปกติแลวคาคงตัวจํานวนเต็มที่ไมม ีL ตอทายจะใชไดกับตวัแปรแบบ long ก็ตาม ตัวอยางเชน ถาเรามีเมธอดสองเมธอดนี้ในคลาสเดียวกัน

boolean run(int mile) { /* */ } boolean run(long mile) { /* */ }

เวลาเรียกใชตองเรียกตางกนัดังนี ้myCar.run(10); myCar.run(10L);

ถาตัวแปรสงผานเปน float กบั double ก็ตองแยกความแตกตางในทํานองเดียวกัน ตัวอยางโปรแกรมในกรณีที ่argument เปนตัวเลข คา default compiler จะถือวา จํานวนเต็มเปน integer และ ทศนิยมเปน double

public class A{ static void doSomething(int i) {

System.out.println("int"); }

static void doSomething(byte b) { System.out.println("byte"); }

static void doSomething(double d) { System.out.println("double"); }

static void doSomething(float f) { System.out.println("float"); };

Page 7: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 215

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

public static void main(String args[]){ doSomething(13); // int doSomething((byte)13); // byte doSomething(0.666);// double doSomething(0.666f);// float

} }

ผลลัพธที่ไดคือ int byte double float

ตัวอยาง ในกรณีที่ argument เปน null compiler จะเลือก argument class ที่มีรายละเอียดมากที่สุด public class B {

static void doSomething(Object obj) { System.out.println("Object");

}; static void doSomething(String str) {

System.out.println("String"); }; public static void main(String args[]){

doSomething(null); // String doSomething((Object)null); // Object

} } ผลลัพธที่ไดคือ String Object

Page 8: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 216

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

class Vehicle { int numberOfWheels; boolean hasEngine; void run(){ // (1)

System.out.println("I am running"); }

} class PrivateCar extends Vehicle {

int numberOfPassengers; void playCD() {

System.out.println("CD is playing."); } void run() { // (2)

System.out.println("I am a running car."); }

} public class BuildACar5 {

public static void main(String[] args) { PrivateCar toyota = new PrivateCar(); toyota.run(); // (3)

} } ผลลัพธที่ไดจากการรัน I am a running car.

การโอเวอรไรด(Override) เราสามารถสราง เมธอด ที่มีช่ือเหมือน เมธอด ของซูปเปอรคลาสในสับคลาสไดดวย เราเรียกวา

การโอเวอรไรด(override) เมธอดใหมใน sub class จะแทนที่ เมธอด เกา ใน super class ตัวอยางเชน

ในบรรทัด (2) เราสรางเมธอด run() ซ่ึงมีช่ือซํ้ากับเมธอด run() ในบรรทัด (1) ถาลองรันโปรแกรมนี้ดูจะพบวาจาวาเวอรชัวนแมทชีนจะเลือกรันเมธอด run() ตัวใหม ดังในตัวอยาง

ขอความที่ปรากฏคือคําวา I am a running car แทนที่จะเปน I am running เหมือนเคยการoverride method นอกจากจะตองใชช่ือ เมธอด ช่ือเดิมแลว การสงผานตัวแปรจะตองเหมือนกันดวย ในตอนกอนหนาเรารูจักการน overload method ขอใหสังเกตวาการoverload กับการoverride มีความหมายตางกันในกรณีของตัวแปรคลาส เราสามารถสรางตัวแปรคลาสชื่อเดิมในสับคลาสไดเหมือนกนั แตตวัแปรตวัใหม

นี้จะไมทับตัวแปรตัวเกาที่นยิามไวในซุปเปอรคลาส เรายังสามารถอางถึงตัวแปรในซุปเปอรคลาสไดอยูดวยการใชคําวา super ตามดวยจุดนําหนาชื่อตัวแปรดังตวัอยางตอไปนี ้

Page 9: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 217

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

class Vehicle { int numberOfWheels; boolean hasEngine; Vehicle() { // (1)

numberOfWheels = 6; hasEngine = true;

} void run(){

System.out.println("I am running"); }

} class PrivateCar extends Vehicle {

int numberOfPassengers; int numberOfWheels; // (2) PrivateCar() { // (3)

numberOfPassengers = 5; numberOfWheels = super.numberOfWheels - 2; // (4)

} void playCD() {

super.run(); // (5) System.out.println("CD is playing.");

} void run() { // (6)

System.out.println("I am a running car."); }

} public class BuildACar6 {

public static void main(String[] args) { PrivateCar toyota = new PrivateCar(); System.out.println(toyota.numberOfWheels); toyota.playCD();

} } ผลลัพธที่ไดจากการรัน 4 I am running CD is playing.

Page 10: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 218

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

class A { void x() { // (1)

System.out.print("I am in A."); }

} class B extends A {

void x() { // (2) System.out.println("I am in B.");

} }

บรรทัด (1) คือ คอนสตรัคเตอรของ Vehicle ซ่ึงเรากําหนดคาเริ่มตนใหตวัแปร numberOfWheels เปน 6 ตัวแปร numberOfWheels พรอมทั้งคาของมันจะสบืทอดไปยังสบัคลาส PrivateCar บรรทัด (2) เราสรางตัวแปรคลาสชื่อเดิมใหกับคลาส PrivateCar แตในคอนสตรัคเตอรของ PrivateCar ในบรรทัด (3) เรายังสามารถอางถึงตัวแปร numberOfWheels ที่นิยามไวในคลาส Vehicle ไดอยูดวยการใช super. นําหนา โดยในกรณีนีเ้รานํามันมากําหนดคาใหกับ numberOfWheels ตัวใหมเมือ่รันโปรแกรมจะไดคาของ numberOfWheels ตัวใหมเปน 4 เพราะถูกหกัออก 2 ดังภาพ

สังเกตวาเราใชคําวา super เรียกตวัแปรคลาสของซูปเปอรคลาสไดเฉพาะในตัวสับคลาสเทานั้น ไมมีวิธีเรียกตวัแปรคลาสของซูปเปอรคลาสนอกตัวสับคลาส เชนการเรียกผานอินสแตนทเชนเดยีวกัน เราสามารถใชคําวา super ในการเรียกแมธธอสของซูปเปอรคลาสที่ถูกโอเวอรรายดไปแลวได อยางเชนในบรรทัด (6) เราโอเวอรรายดแมธธอส run() ไปแลว แตเรายังสามารถเรียกใชงานแมธธอสรันตัวเกาไดในบรรทัด (5) ดวยการใชคําวา super นําหนา ผลที่ไดคือจาวาเวอรชัวนแมทชีนจะรันแมธธอส run() ของซูปเปอรคลาสในแมธธอส playCD() ผลที่ไดจึงเปนดังภาพขางตน การใชคําสั่ง super เรียกแมธธอสของซูปเปอรคลาสทําไดเฉพาะภายในตวัสับคลาสเทานั้น ไมมีวิธีเรียกแมธธอสของซูปเปอรคลาสภายในนอกตัวแมธธอส

ขอสังเกตเกี่ยวกับ super ก็คอืวา super ใชเรียกตัวแปรและแมธธอสของซูปเปอรคลาสที่อยูถัดขึ้นไปหนึ่งระดับเทานั้น ถามีการสรางสับคลาสมากกวาหนึ่งระดับเราไมมีวิธีเรียกตวัแปรและแมธธอสของซูปเปอรที่อยูถัดขึ้นไปกวาซปูเปอรคลาสที่อยูในระดับตดิกับตัวสับคลาสได ตัวอยางเชน

Page 11: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 219

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

class C extends B { void x() { // (3)

System.out.println("I am in C."); } void y() {

super.x(); // (4) }

} public class TestSuper {

public static void main(String[] args) { C c = new C(); c.y(); // (5)

} } ผลลัพธที่ไดจากการรัน I am in B.

คลาส C สืบทอดคลาส B ซ่ึงสืบทอดคลาส A มากอน ทั้งสามคลาสมีแมธธอสชื่อ x() อยูทั้งสิ้น

หรืออีกนัยหนึง่ก็คือ x() ถูกโอเวอรรายดมาโดยตลอด ในบรรทัด (4) แมธธอส y() มีการเรียกแมธธอส x() โดยใช super นําหนา ผลที่ไดคือเมื่อรันแมธธอส y() ในบรรทัด(5) จะไดแมธธอสในคลาส B ที่นยิามไวในบรรทัด (2) เพราะคลาส B เปนซูปเปอรคลาสตัวที่ใกลชิดคลาส c มากที่สุด ดังในภาพ สรุป เมธอดโอเวอรไรด(Override method)

เมธอดโอเวอรไรดเปน Polymorphisms Method ที่จําแนกขณะ runtime โดย jvm จะตรวจสอบวาออบเจ็คที่ถูกสรางในขณะนั้นเปนชนิดใดแลวจะนําเมธอดในออบเจค็นั้นๆมาทํางาน

เมธอดที่มี Modifier เปน final และ private จะ Overriding ไมได สวน default ถา Subclasses อยูคนละ package กับ superclass จะ Overriding ไมได

class A { void doSomething() {

System.out.println(“Class A”); } }

Page 12: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 220

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

สรุป กฎของการโอเวอรไรด 1.. arguments list ของเมธถอดตองเหมือนตนแบบ

public class B extends A { void doSomething() {

System.out.println(“Class B”); }

public static void main(String args[]){ A a = new A(); a. doSomething (); // Class A a = new B(); a. doSomething (); // Class B //B b = new a(); // Compile Error

} } ผลลัพธที่ไดคือ Class A Class B

class A { int i=0; void doSomething() {

i = 5; }

} public class B extends A {

int j = 0; void doSomething() { j = 10; i += j; }// Overridden

void doSomething(int k) { j = 11; i += j*k; } // Legal but Not Overriding

}

Page 13: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 221

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

2. return type ของเมธถอดตองเหมือนตนฉบับ 3. Access level ของ Overriding method ตองไมนอยกวาตนแบบ

public class A { int i=0; void doSomething() {

i = 5; }

} class B extends A {

int j = 0; void doSomething() { j = 10; i += j; }// Overridden

int doSomething() { j = 11; return i += j*k; } // Compile Error

}

public class A { int i=0; void doSomething() {

i = 5; }

} class B extends A {

int j = 0; protected void doSomething() { j = 10; i += j; }// Overridden

private int doSomething() { j = 11; return i += j*k; } // Complie Error

}

Page 14: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 222

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

4. ในกรณีที ่Method ตนแบบมีการ throws Exception ศึกษาเพิ่มเติมไดในบทที่ 12 o Overriding Method ไมจําเปนตอง Throws Exception o ถา Overriding Method มีการ Throws Exception แลว Exception Class ที่ Overriding

Throws นั้นตองเปน Same Class หรือ Sub Class ของ Exception ที่ตนแบบ Throws o กรณีที่ Method ตนแบบไมมกีาร Throws Exception Overriding จะมีการ Throws ไมได

ตัวอยาง โปรแกรมเมธอดทีม่ีการ throws Exception Method ที่ 1 ถึง method ที่ 3 เปน overriding method ที่สามารถสรางได โดยที่เลือกทําการคอมไพลทีละ method สวน method ที่ 4 เปน method ที่ไมสามารถคอมไพลไดเนื่องจาก class Exception เปน super class ของ class IOException เมื่อทําการ override ดวย method ที่ 4 จะทําใหเกิด compile error ขึ้น

import java.io.*; class A { int i=0; void doSomething() throws IOException { i = 5; } } public class B extends A { int j = 0; void doSomething() { // method ที่ 1 j = 10; i += j; }// Overridden

void doSomething() throws IOException {// method ที่ 2 j = 11; } // Overridden

void doSomething() throws FileNotFoundException {// method ที่ 3 j = 11; } // Overridden

/* void doSomething() throws Exception {// method ที่ 4 j = 11; } Compile Error in This method*/ }

Page 15: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 223

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

5. ไมสามารถทําการ Overriding สําหรับ Method ที่เปน final หรือไมไดรับการสืบทอดได จะกลาวถึงคียเวิรด final ในหัวขอถัดไป ตัวอยาง โปรแกรมที่มีการ Overriding กับ method ที่เปน final

class A { int i=0; private void doSomething() {

i = 5; } final void doSomethingMore() {

i = 5*2; }

} public class D extends A {

private void doSomething() { i = 10;

} // Legal but not override void doSomethingMore() {

i = 5*2; } // Complie Error เนื่องจาก overridden method ที่เปน final

} ผลจากการคอมไพล D.java:17: doSomethingMore() in D cannot override doSomethingMore() in A; overridden method is final void doSomethingMore() { ^ 1 error

Page 16: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 224

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

final class A { // (1) } /* class B extends A { // (2) } */ public class TestFinal {

public static void main (String[] args) { A a = new A(); // (3)

} }

คลาสถาวร(final class) คลาสถาวร คือ คลาสที่ไมอนุญาตใหนําไปใชสืบทอด เราสามารถกําหนดใหคลาสของเราเปน

คลาสถาวรไดดวยการใชคําสั่ง final นําหนาคําสั่ง class ดังตัวอยางตอไปนี ้

คลาส A ในบรรทัด (1) ถูกกําหนดใหเปน คลาสถาวร การสรางคลาส B ในบรรทัด (2) จึงทํา

ไมไดเพราะคลาส B สืบทอดคลาส A ประโยชนของคาํสั่งถาวรคือ การปองกันไมใหนกัเขียนโปรแกรมคนอื่นเอาคลาสของเราไปสืบทอดโดยไมบอกกลาว เพราะอาจทําใหเกิดการสับสนตอนที่เรากลาวถึงคลาสนามธรรม จะเหน็ไดวา คลาสนามธรรม มักใชเปนตนแบบสําหรับคลาสอื่น ดงันั้นจึงไมมเีหตุผลที่จะกําหนดใหคลาสนามธรรมเปนคลาสถาวร เพราะคลาสนามธรรมจะมีประโยชนก็ตอเมื่อเรานํามันไปสืบทอด ดวยเหตุนี ้ คําสั่ง final และคําสั่งabstract จะใชนําหนาคลาสเดียวกันไมได คลาส String เปนคลาสถาวร คุณไมสามารถสรางคลาสที่สืบทอดคลาส String ได เมธอดถาวร(Final Method) หากไมตองการใหเกดิการ Overriding กับเมธอดใหใสคยีเวิรด final ไวหนาชื่อ method ดังนี ้

class A{ final void print(){ System.out.println("Final method"); } } class B extends A{ void print(){ // error เนื่องจาก คลาส A มีคําวา final อยูหนาชื่อเมธอดไมให overiding System.out.println("abstract method"); } }

Page 17: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 225

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

ตัวแปรถาวร(Final variable) กําหนดใหตัวแปรมีคาคงที่(เหมือน const ใน C language) เชน

final int MAX = 5; static final double PI = 3.1428714285; สรุป คียเวร์ิด final

o Final Class หมายถึง คลาสที่ไมสามารถนําไปทําการสบืทอดคุณสมบัติได o Final Method หมายถึง เมธอด ที่ไมสามารถทําการ overriding ได o Final Variable หมายถึง Variable ที่ไมสามารถเปลี่ยนแปลงได o Final Argument หมายถึง Argument ที่ไมสามารถเปลี่ยนแปลงได

class testStaticVariable{ final static double PI = 3.1428714285; //static final double PI = 3.1428714285; // error : ตองประกาศ final กอน static public static void main(String[] args){ System.out.println(PI); //final static double PI = 3.1428714285; //error : modifier static ไมใหประกาศใน method } }

Page 18: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 226

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

คลาสนามธรรม(Abstract class) คลาสคือนิยามของวัตถุ เราสรางวัตถุขึ้นจากการสรางอินสแตนทของคลาส แตในภาษาจาวาเรา

สามารถสรางคลาสที่ไมอนุญาตใหนําไปสรางอินสแตนทไดดวย เราเรียกคลาสเหลานั้นวา คลาสนามธรรม (Abstract class)ลองพิจารณาตวัอยางตอไปนี ้

ในบรรทัด (1) เปนการนิยามคลาส A ซ่ึงกําหนดใหเปนคลาสนามธรรมดวยการใชคําสั่งabstract

นําหนาคําสั่ง class ผลที่ไดก็คือ หามสรางอินสแตนทของคลาส A ดังในบรรทัด(2) คุณอาจสงสัยวาทําไมตองมีการหามไมใหมกีารสรางอินสแตนทของคลาส ในเมื่อจดุประสงคของการสรางคลาสก็คือการสรางอินสแตนท ในบางกรณีนักเขยีนโปรแกรมตองการลดขนาดของโปรแกรมลงเวลาที่ตองสรางคลาสหลายๆ คลาสที่มีคุณสมบัติคลายๆ กัน นักเขยีนโปรแกรมจะสรางคลาสนามธรรมขึ้นมากอน คลาสนามธรรมจะบรรจุสวนที่ซํ้ากันของคลาสเหลานั้นเอาไว จากนัน้นักเขยีนโปรแกรมก็จะสรางคลาสเหลานั้นดวยการสืบทอดคลาสนามธรรมแลวเติมรายละเอียดปลีกยอยที่แตกตางลงไปทีหลัง วิธีนี้โปรแกรมจะมขีนาดเล็กลงเพราะไมมีการนิยามตวัแปรคลาส และเมธอดที่ซํ้าๆ กัน แตเนื่องจากคลาสนามธรรมมีไวเพียงเพื่อจุดประสงคในการลดขนาดโปรแกรม นักเขียนโปรแกรมจึงระวังไมใหใครเอาคลาสนามธรรมไปใชดวยการหามมิใหอินสแตนทคลาสนามธรรมที่ผานมาเราสรางคลาส Vehicle ขึ้นมาโดยประกาศตวัแปรคลาส numberOfWheelshasEngine และเมธอด run() ซ่ึงเปนลักษณะรวมของรถยนตทุกชนิด จากนั้นเราก็สรางคลาส Truck และ PrivateCar ใหสืบทอดคลาส Vehicle ซ่ึงจะไดตวัแปรคลาสและเมธอดมาโดยอัตโนมัต ิ จากนั้นกน็ยิามตัวแปรและเมธอดอื่นที่เปนลักษณะเฉพาะของรถแตละชนิดในตัวของคลาสนั้นๆ เองทีหลัง ในกรณีถานักเขียนโปรแกรมไมตองการใหใครสรางอินสแตนท Vehicle นักเขียนโปรแกรมสามารถทําไดโดยกําหนดใหคลาส Vehicle เปนคลาสนามธรรม

และนอกจากนั้นยังปองการใหทุก sub class ที่ inherit super class ซ่ึงจําเปนจะตองมีทุก ๆ เมธอด ที่ตองทําการ override ดวย เชน

abstract class A { // (1) } public class TestAbstract {

public static void main (String[] args) { // A a = new A(); // Error (2) }

}

Page 19: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 227

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

abstract class A{ abstract void print(); int cal(){ return 0; } } //หากภายใน class มีอยางนอย 1 method ที่เปน abstract แลว class นั้นตองเปน abstract ดวย //ถา class ใดเปน abstract ไมจําเปนที ่จะมี abstract method อยูภายใน class B extends A{ void print(){ System.out.println("abstract method"); } void show(){ System.out.println("print from show"); } } class C extends A{ void print(){ System.out.println(“print from C class"); } void show(){ System.out.println(“HaHa from C”); } } //ทุก class ที่ inherit จาก class A จําเปนตองมี method print()เสมอ เพื่อเปน override method class testOverid{ public static void main(String args[]){ B subB = new B(); subB.print(); subB.show(); C subC = new C(); subC.print(); subC.show();

} } ผลลัพธที่ไดคือ

abstract method print from show print from C class HaHa from C

Page 20: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 228

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

ตัวอยาง แสดงการขยาย abstract class

abstract class One{ void prName(){System.out.println("One"); } abstract void greet(); } abstract class Two{ void prName(){System.out.println("Two");} } class SubOne extends One{ void greet(){System.out.println("Hello");} }; class SubTwo extends Two{} class Abstract2{ static public void main(String args[]){ //new One();//error:One is abstract; cannot be instantiated //new Two();//error:Two is abstract; cannot be instantiated (new SubOne()).greet(); (new SubTwo()).prName(); } }; ผลลัพธที่ไดคือ

Hello Two

Page 21: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 229

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

ตัวอยาง แสดง abstract class ไมครบ ตัวอยาง หากทําการ Override ไมครบ

abstract class One{ abstract void greet1(); abstract void greet2(); } abstract class Two extends One{ void greet1(){System.out.println("Hello");} } class Three extends Two{ void greet2(){System.out.println("Hi");} } class Abstract3{ static public void main(String args[]){ //new Two();error:Two is abstract;cannot be instantiated Three t = new Three(); t.greet1(); t.greet2(); } }// Two เปน abstract class จะสราง instance ไมได นําไปประกาศ reference ได ผลลัพธที่ไดจากการรัน

Hello Hi

abstract class Shape{ static final double PI = 3.141592; abstract double area(); abstract String getName(); }

Page 22: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 230

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

class Circle extends Shape{ double r; static final String name = "Circle"; Circle(double r){this.r = r;} double area(){return PI * r *r;} String getName(){return name;} double circumference(){return 2*PI*r;} } /*หากไม override method area และ getName จะเกดิ error ขึ้นเนื่องจากทั้งสอง method เปน abstract method*/ class Rectangle extends Shape{ double w,h; static final String name = "rectangle"; Rectangle(double w, double h){this.w = w ; this.h =h;} double area(){return w*h;} String getName(){return name;} } class AbsEx{ public static void main(String args[]){ Shape[] s = new Shape[3]; s[0] = new Circle(2.0); s[1] = new Rectangle(1.0 , 3.0); s[2] = new Circle(4.5); for(int i = 0 ; i < s.length ; i++){ System.out.println(s[i].getName()+","+s[i].area()); } } } ผลลัพธที่ไดจากการรัน Circle,12.566368 rectangle,3.0 Circle,63.617238

Page 23: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 231

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

สรุป คียเวรด Abstract o Abstract Method หมายถึง method ที่ยังไมมีกระบวนการทํางานใดๆเลย ไมมี method body

ซ่ึง class ที่สืบทอดไปจะตองทําการ implement ใหมีกระบวนการทํางาน o Abstract method ตองเปนสมาชิกของ Abstract class เทานั้น แต Abstract class ไม

จําเปนตองมีสมาชิกเปน Abstract Method คียเวิรด Interfaces มีลักษณะคลายกับ abstract class เพียงแตใน abstract class ไมมีช่ือตัวแปร แตมีเฉพาะ abstract methods หรือคาคงที่เทานั้น นั่นหมายความวา เมื่อโปรแกรมใดก็ตามมีการนิยาม Interface ไว แลว ทุกคลาสในโปรแกรมนั้นจะตองสราง method ที่มีช่ือตามที่ระบุไวใน Interface ดวย โดยเนื้อหาของ method อาจจะแตกตางกันไปในแตละ class ขึ้นอยูกับความตองการในการใชงาน (แตช่ือ method ตองเปนชื่อเดียวกัน) ลักษณะการเขียนโปรแกรมเชนนี้เรียกวา มีเพียง 1 ช่ือ แตทํางานไดหลายอยาง(One interface, Multiple method) หรือในทางการเขียนโปรแกรมเชิงวัตถุ จะมีลักษณะที่เรียกวา Polymorphism การใชงาน interface จะเหมือนกับ abstract class คือ นํา interface ไปประกาศ reference ได แตนําไปสราง instance ไมไดจําเปนตองสราง class ที่มี implementations ของ abstract methods ใน interface นั้นใหครบเสียกอนจึงจะนําคลาสนั้นไปใชงานไดเหมือนกับเปนคลาสลูกคลาสหนึ่งของ interface นั้น

การนิยาม interface ระบุคําวา interface แทน class การสราง method ที่ระบุใน interface ระบุคําวา implements แลวตามดวย interface ไวในบรรทัด

ของการกําหนดชื่อ class จากนั้นกําหนดรายละเอียดไวใน class นั้น interface ใชในการระบุกลุมของ method ที่ใชไดกบั class ตั้งแต 1 class ขึ้นไป การกําหนด interface จะคลายกับการกําหนดคลาสๆหนึ่งแตใช keyword 'interface' แทน 'class'

และทุก methods ของ interface จะตองเปน abstract method โดย default ซ่ึงจะระบุดวย keyword 'abstract' หรือไมก็ได รวมทั้งทุกๆ fields ใน interface จะตองเปนคาคงที่ ซ่ึงอาจจะระบุดวย static และ final หรือไมก็ได

ประโยชนของการนํา Interface มาใชนัน้ เพื่อหลีกเลี่ยงปญหาของการ Inherite ระหวาง superclass กับ subclass เพราะ เมื่อใช interface โปรแกรมจะไมตรวจสอบการ Inherite ระหวาง classes

Page 24: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 232

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

ตัวอยาง การโปรแกรมสราง interface และ การสราง method ที่ระบุใน interface

interface c{ public void fc1(); public String fc2(); public double fc3(); } interface d{ public void fd1(); public void fd2(double x); } class test implements c{ // implements c,d => OK public void fc1() { } public String fc2(){ return "zzz"; } public double fc3(){ return 5; } }

Page 25: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 233

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

ตัวอยาง การประกาศ Interface และการเรียกใชงาน

interface Greeting{ static final String s = "Hello"; void greet(); } class Hello implements Greeting{ public void greet(){ //greet() must be public System.out.println(s); } } class Interface1{ public static void main(String args[]){ Hello h = new Hello(); h.greet(); } } ผลลัพธที่ได Hello

//using interface Greeting from Greeting.java //using class Hello from Interface1.java class Hi implements Greeting{ public void greet(){ System.out.println("Hi"); } void moreGreet(){ System.out.println("How do you do?"); } } class Interface2{ static void test(Greeting g){g.greet();} public static void main(String args[]){ test(new Hello()); Hi g = new Hi(); test(g); g.moreGreet(); } }

Page 26: บทที่ 9 การพ้องรูป

บทท่ี 9 การพองรูป หนาที่ 234

เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ

สรุป คียเวิรด Interface

o กลาวไดวา Interface ก็คือ pure abstract class นั่นเอง โดย method ทุกตวัที่ประกาศใน interface จะถือวาเปน public abstract โดยปริยาย สวน Variable นั้นหากมีจะตองกําหนดเปน public static final เทานั้น

o Interface สามารถสืบทอด จาก interface อ่ืนใด แตไมสามารถสืบทอดจาก class ได o Interface ใชสําหรับให class ทําการ implement แตตัวมนัไมสามารถ implement ได o Interface ใชสําหรับรองรับกระบวนการ Polymorphism o หนึ่ง class สามารถ implement interface ไดไมจํากดั

แบบฝกหัด 1. Polymorphism คืออะไร จงอธิบายพรอมยกตวัอยางการใชงาน Polymorphism 2. Interface คือะไร มีประโยชนอยางไร จงอธิบายพรอมยกตัวอยาง 3. Interface แตกตางจาก abstract class อยางไร จงอธิบายพรอมยกตัวอยาง 4. Interface ตางหรือเหมือนกบั Overloading Method อยางไร จงอธิบาย 5. Inherite เกี่ยวของอยางไรกบั Interface

ผลลัพธที่ไดคือ Hello Hi How do you do?