SlideShare ist ein Scribd-Unternehmen logo
1 von 28
Downloaden Sie, um offline zu lesen
การสืบทอดคุณสมบัติของคลาส
Inheritance
วัตถุประสงค
♦ เพื่อใหมีความรูความเขาใจคุณสมบัติการสืบทอดของการเขียนโปรแกรมเชิงวัตถุ
♦ เพื่อใหมีความรูความเขาใจในการทํางานของคําสั่งการสืบทอดในภาษาจาวา
♦ เพื่อสามารถนําหลักการสืบทอดไปเขียนโปรแกรมประยุกตใชกับงานจริงได
บทที่
8
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 182
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
เนื้อหาบทเรียน
♦ การสืบสกุล(Inheritance)
♦ คียเวิรด This
♦ คียเวิรด Super
♦ คียเวิรด Instanceof
♦ การสืบทอดคุณสมบัติของคลาสที่มากกวา 2 ขั้น
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 183
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
Parent
Son
Super Class
Sub Class
A
B C
Method B Method C
Method A
การสืบทอด(Inheritance)
เราสามารถสรางคลาสใหมโดยอาศัยคลาสที่มีอยูแลวเปนตนแบบ เราเรียกคลาสใหมวา สับคลาส
(sub class) ของคลาสเกา และเรียกคลาสเกาวา ซูปเปอรคลาส(Supper class) ของคลาสใหม ตัวแปร
คลาสและ method จะไดรับการสืบทอดไปยังสับคลาสโดยอัตโนมัติ เหมือนกับการสืบทอดลักษณะทาง
พันธุกรรมจากพอไปสูลูก
ในภาษาจาวาจะยอมใหซับคลาสสืบทอด(inherited)คุณสมบัติไดจากซุปเปอรคลาสไดเพียงคลาส
เดียวเทานั้น ซึ่งไมเหมือนกับภาษา C++ ที่ซับคลาสสามารถสืบทอดคุณสมบัติไดจากหลายซุปเปอร
คลาส
กลาวไดวาคุณสมบัติการสืบทอด(Inheritance) คือการที่ Class หนึ่งๆสามารถสืบทอดคุณสมบัติ
บางประการจาก Class อื่น แลวเพิ่มคุณสมบัติเฉพาะของ Class นั้นเขาไป Class ที่ไดรับการสืบทอด
คุณสมบัติเรียกวา Subclasses สวน Class ที่เปนตนแบบเรียกวา Superclass ประโยชนของคุณสมบัติการ
สืบทอดคือ เปนการชวยใหไมตองออกแบบ พัฒนา สวนที่ซ้ําหลายๆรอบ(reusable) Class หนึ่งๆจะมี
Superclass ไดเพียง Class เดียวเทานั้น (Single Inheritance) ดังรูป
รูปแบบของการประกาศการสืบทอดคุณสมบัติของคลาส
class subclass_name extends superclass_name{
[member;]
}
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 184
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
ตัวอยาง โปรแกรมที่มีคุณสมบัติการสืบทอด
class A{
void printA(){
System.out.println("A");
}
}
class B extends A{
void printB(){
System.out.println("B");
}
}
class TestInherit1{
public static void main(String args[]){
A x = new A();
x.printA();
B y = new B();
y.printA();
y.printB();
}
}
ผลลัพธที่ได
A
A
B
ตัวอยาง โปรแกรมที่มีคุณสมบัติการสืบทอด
class AA{
int i,j;
void printA() {
System.out.println(" i = " + i + " : j = " + j);
}}
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 185
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
class BB extends AA{
int k;
void printB(){
System.out.println(" k = " + k);
}
void sum( ) {
System.out.println("i+j+k="+(i+j+k));
}
}
class TestInherit2{
public static void main(String args[]){
AA superClass = new AA();
BB subClass = new BB();
System.out.println("print from superclass");
superClass.i = 10;
superClass.j = 20;
superClass.printA();
System.out.println();
System.out.println("print from subclass");
subClass.i = 3;
subClass.j = 4;
subClass.k = 5;
subClass.printA();
subClass.printB();
subClass.sum();
}
}
ผลลัพธที่ไดคือ
print from superclass
i = 10 : j = 20
print from subclass
i = 3 : j = 4
k = 5
i+j+k=12
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 186
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
ตัวอยาง โปรแกรมที่มีการเรียกใชคลาสที่มีการสืบทอด
class TestInherit3{
static void methodA(A a){
a.printA();
}
static void methodB(B b){
b.printB();
}
public static void main(String args[]){
A x = new A();
methodA(x);
B y = new B();
methodA(y);
methodB(y);
A z = new B(); // super : sub
z.printA();
//z.printB();
}
}
/*method ที่รับ instance ของคลาสแมเปนพารามิเตอรจะสามารถรับ instance ของ class ลูกเปน
parameter ไดดวย*/
ผลลัพธที่ไดคือ
A
A
B
A
หมายเหตุ : หากตองการปองกันการเขาถึงdata member(attribute และ method)ของ super class ใหใส
สวนขยายหนา data member ดวยคําวา private
ตามนิยามของ Sun แบง ความสัมพันธระหวาง Classes เปนสองลักษณะคือ
– IS-A เปนความสัมพันธที่ Class หนึ่งเปน Subclass ของอีก Class หนึ่ง
– HAS-A เปนความสัมพันธที่ Class หนึ่งเปนสวนประกอบ ของอีก Class หนึ่ง
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 187
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
ตัวอยางการนําคุณสมบัติการสืบทอดมาประยุกตใชในการเขียนโปรแกรม เชน คลาส Vehicle
นิยามสิ่งที่ใชตัดสินวาวัตถุที่จัดวาเปนรถยนตตองมีคุณสมบัติและพฤติกรรมอะไรบาง คราวนี้ถาเรา
ตองการสรางนิยามที่มีความเฉพาะเจาะจงมากขึ้น เชนนิยามของรถบรรทุก นิยามของรถเกง เราอาจสราง
คลาสใหมชื่อ Truck กับ PrivateCar ซึ่งนิยามคุณสมบัติและพฤติกรรมที่มีเฉพาะแตในรถบรรทุก
และรถเกง มีความสัมพันธกันดังรูป
แทนที่เราจะสรางคลาสทั้งสองขึ้นมาใหมตั้งแตตน เราอาจใชคลาส Vehicle เปนตนแบบเพราะ
ทั้งรถบรรทุก และรถเกงยอมตองมีลอ มีเครื่อง และวิ่งได จากนั้นคอยเติมคุณสมบัติและพฤติกรรมอื่นๆ ที่
มีเฉพาะในรถบรรทุก หรือรถเกงเขาไป เราทําเชนนี้ไดโดยการสรางสับคลาสของซูปเปอรคลาส Vehicle
สองตัวชื่อ Truck และ PrivateCar ดังตัวอยางตอไปนี้
vehicle
Truck PrivateCar
class Vehicle {
int numberOfWheels;
boolean hasEngine;
void run(){
System.out.println("I am running.");
}
}
class Truck extends Vehicle { // (1)
float maximumLoad; // (2)
void load(float weight) { // (3)
if (weight <= maximumLoad)
System.out.println("I am carrying a " + weight + "-pound load.");
}
}
}
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 188
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
ในบรรทัด (1),(4) เราประกาศคลาสใหมชื่อ Truck และ PrivateCar ซึ่งเปนสับคลาสของคลาส
Vehicle ที่มีอยูแลว โดยเราใชคําสั่ง extends ตามดวยชื่อซูปเปอรคลาส สิ่งที่ไดมาโดยอัตโนมัติคือทั้ง
คลาส Truck และ PrivateCar จะมีตัวแปรชื่อ noOfWheels, hasEngine และมีmethodชื่อ run() พวงมาดวย
ทันทีจากนั้นเราสามารถสรางตัวแปรคลาสและmethodเพิ่มเติมได เพื่อใชเปนสิ่งที่บอกลักษณะที่มีเฉพาะ
แตในรถบรรทุกหรือรถเกง ในบรรทัด(2)เราสรางตัวแปร maximumLoad ใหคลาส Truck เพื่อใชในระบุ
น้ําหนักบรรทุกสูงสุดของรถบรรทุก และสรางmethod load() ในบรรทัด (3) เพราะสิ่งที่รถบรรทุกตองทํา
ไดคือการบรรทุกของในบรรทัด (5) เราสรางตัวแปร numberOfPassengers ใหคลาส PrivateCar เพื่อใช
ระบุจํานวนผูนั่ง รถเกงควรมีเครื่องเลนซีดีดวย เพื่อใหเกิดความแตกตางกับรถบรรทุก ดังนั้นเราจึงสราง
method playCD() ในบรรทัด (6)
คําสั่งในmethod main() เปนการสรางอินสแตนทใหกับคลาส Truck และ PrivateCar อยางละ
หนึ่งอินสแตนท สังเกตวาอินสแตนททั้งสองมีตัวแปร numberOfWheels และmethod run()ทั้งที่ไมได
class PrivateCar extends Vehicle { // (4)
int numberOfPassengers; // (5)
void playCD() { // (6)
System.out.println("CD is playing.");
}
}
public class BuildACar4 {
public static void main(String[] args) {
Truck isuzu = new Truck();
PrivateCar toyota = new PrivateCar();
isuzu.numberOfWheels = 6;
toyota.numberOfWheels = 4;
isuzu.maximumLoad = 1500.00F;
toyota.numberOfPassengers = 5;
isuzu.load(700.0F);
isuzu.run();
toyota.playCD();
toyota.run();
}
}
ผลลัพธคือ
I am carrying a 700.0-pound load.
I am running.
CD is playing.
I am running.
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 189
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
สรางไวในคลาส ที่เปนเชนนี้เพราะคลาสทั้งสองสืบทอดคุณลักษณะของคลาส Vehicle ผลการรัน
โปรแกรมขางตนจะเปนดังผลลัพธที่แสดง
เราสามารถสรางสับคลาสของสับคลาสไดดวย ดังนั้นคุณลักษณะของคลาสสามารถสืบทอดตอ
กันไปไดเรื่อยๆ ไมมีที่สิ้นสุด คลาสคลาสหนึ่งมีไดหลายสับคลาสเชนในกรณีของคลาส Vehicle มีสอง
สับคลาสคือ Truck และ PrivateCar แตคลาสคลาสหนึ่งในภาษาจาวามีได แคซุปเปอรคลาสเดียว
กลาวคือเมื่อ Truck สืบทอดคุณลักษณะจากซุปเปอรคลาส Vehicle แลว คลาส Truck ไมสามารถสืบทอด
คุณลักษณะจากคลาสอื่นไดอีก คําสั่ง extends จึงตามดวยชื่อซุปเปอรคลาสไดแคซุปเปอรคลาสเดียว
เทานั้น
Key word : this
ในการเขียนโปรแกรมเพื่อสราง class บางครั้งอาจเกิดปญหาตัวแปรคลาส กับ ตัวแปรทองถิ่นใน
method ในคลาสเดียวกัน สามารถมีชื่อซ้ํากันได เพราะตัวแปรคลาสเกิดขึ้นเมื่อมีการสราง instance แตตัว
แปรทองถิ่นเกิดขึ้นเมื่อมีการเรียกใช method และตายไปทันทีที่ method รันเสร็จ จาวาจึงแยกแยะความ
แตกตางระหวางตัวแปรทั้งสองตัวไดแตบางครั้งก็เกิดการสับสน คําสั่ง this จึงมีไวแยกแยะความแตกตาง
ใหชัดเจนไปเลย ตัวอยางเชน
class TestThis1 {
int a; // (1)
float b; // (2)
char c; // (3)
void x(int a, float b,char i){ // (4)
char c; // (5)
this.a = a; // (6)
c = i; // (7)
this.y(); // (8)
y(); // (9)
}
void y() { // (10)
System.out.println("Hello World");
}
}
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 190
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
คลาสนี้มีตัวแปรคลาสสามตัวไดแก a , b และ c ในบรรทัด (1)(2)(3) method x() มีการสงผาน
ตัวแปรที่มีชื่อเหมือนตัวแปรคลาส a และ b ในบรรทัด (4) อีกทั้งยังประกาศตัวแปรภายในmethod ชื่อ c
ซึ่งซ้ํากับตัวแปรคลาสอีก ในบรรทัด (5) คําสั่งในบรรทัด (6) ใชคําสั่ง this ตามดวยจุดนําหนา a เปนการ
ชี้เฉพาะเจาะจงลงไปวา หมายถึงตัวแปรคลาส a ที่ประกาศไวในบรรทัด (1) คําสั่งนี้เปนการกําหนดคาตัว
แปรคลาส a ใหมีคาเทากับตัวแปรสงผาน a ซึ่งอยูหลังเครื่องหมายเทากับ ตัวแปรสงผานไมมีคําวา this
นําหนาคําสั่งในบรรทัด (7) เปนการอางถึงตัวแปร c ที่ประกาศไวในบรรทัด (5) เพราะไมมี this นําหนา
สรุปก็คือ ถามีการใชชื่อซ้ํากัน การใชชื่อตัวแปรเฉยๆ จะถือวาเปนตัวแปรภายใน method ถาตองการอาง
ถึงตัวแปรคลาสตองระบุ this ดวยเสมอ แตถาไมมีการใชชื่อซ้ํากัน ไมตองระบุ this ก็ไดเหมือนกันที่เรา
เคยเขียนกัน คําสั่ง this ใชระบุเฉพาะเจาะจงไดดวยวาหมายถึง method ในคลาสเดียวกันดังที่ใชใน
บรรทัด (8) แตเนื่องจากไมมีความสับสนในกรณีของ method อยูแลว (เพราะไมมี method ทองถิ่น) การ
ระบุ this จึงไมจําเปนสําหรับการเรียก method บรรทัด (8) กับ บรรทัด(9) จึงมีความหมายเหมือนกัน
ตัวอยาง การใช keyword this
แตถาเอาเครื่องหมาย // บรรทัดที่ (1) ออกแลวใสเครื่องหมาย // หนาบรรทัดที่(2) แทน ผลลัพธ
จะกลายเปน Pokemon แทน
class TestThis2 {
String name = "Pokemon";
TestThis2(String name){
//name = name; // (1)
this.name = name ;//(2)
}
void print(){
System.out.println(name);
}
public static void main(String[] args) {
TestThis2 t = new TestThis2("Sompong");
t.print();
}
}
ผลลัพธคือ
Sompong
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 191
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
ตัวอยาง การใช keyword this
คลาส TestThis3 ในตัวอยางนี้มี field r และ i และมี constructor รับพารามิเตอรที่ชื่อ r และ i
เขามา เพื่อกําหนดคาใหแก fields ที่มีชื่อเหมือนกัน ถาหากเขียนประโยคกําหนดคาเปน r = r และ i=i ก็
จะเปนการกําหนดคาใหแกตัวเองไมวาชื่อที่อางถึงนี้จะหมายถึงชื่อใด ซึ่งไมใชสิ่งที่ตองการ เราจึงตอง
ใช this ชวยในการระบุวา this.r หมายถึง r ตัวที่เปนสมาชิกในคลาส สวน r เพียงตัวเดียวนั้นคือ ตัวที่
เปนพารามิเตอร สังเกตวาชื่อพารามิเตอรจะบังชื่อที่อยูขางนอก method และในทํานองเดียวกัน this.i
กับ i หากใน method นั้นไมมีพารามิเตอรที่มีชื่อเหมือนกับ field ของคลาสอยางเชน add() และ print( )
ในตัวอยางนี้ การอางถึง r หรือ i จะหมายถึงตัวที่เปน field ของคลาส
นอกจากนั้นภาษาจาวา ยังมีการใช this ในอีกความหมายหนึ่งคือ ใช this ในการเรียก method
จะหมายถึงการเรียก constructor ของคลาสนั้น ดังตัวอยาง
this( )
class TestThis3 {
double r, ;
TestThis3(double r, double i ){
this.r = r ;
this.i = i;}
public void add(TestThis3 t){
r+= t.r ;
i += t.i;
}
void print(){
System.out.println(r + " + i " + i );
}
}
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 192
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
คงจําไดวาถาไมมีการกําหนดคาเริ่มตนของตัวแปรคลาสไว เวลาสรางอินสแตนท จาวาเวอรชัวน
แมทชีน จะกําหนดคาปกติให การกําหนดคาเริ่มตนทําไดดวยการกําหนดเขาไปเลยตอนนิยามคลาส จา
วามี method พิเศษชนิดหนึ่งชื่อวา คอนสตรัคเตอร ซึ่งเปน method ที่มีไวสําหรับการกําหนดคาเริ่มตน
ใหกับอินสแตนทโดยเฉพาะ คอนสตรัคเตอรเปนทางเลือกอีกทางหนึ่งของการกําหนดคาใหตัวแปรคลาส
ลองพิจารณาการกําหนดคาเริ่มตนใหตัวแปรคลาสดวยการใชคอนสตรัคเตอรดังตัวอยางขางลางนี้
ตัวอยาง การใชงาน constructor
Method constructor คือ method ในบรรทัด (1) method constructor ตองมีชื่อเหมือนชื่อคลาส
เสมอ แตตามดวย () เพื่อใหรูวาเปน method และตองไมมีคําวา void หรือชื่อชนิดของตัวแปรใดๆ
class Vehicle {
int numberOfWheels;
boolean hasEngine;
Vehicle() { // (1)
numberOfWheels = 6;
hasEngine = true;
}
void run(){
System.out.println("I am running");
}
}
public class BuildACar1 {
public static void main (String[] args) {
Vehicle myCar = new Vehicle();
System.out.println("My car has " + myCar.numberOfWheels + "wheels.");
System.out.println("That my car has an engine is " +myCar.hasEngine + ".");
}
}
ผลลัพธคือ
My car has 6wheels.
That my car has an engine is true.
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 193
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
นําหนาชื่อคอนสตรัคเตอร ภายในบลอคปกกาของคอนสตรัสเตอรเราใสคําสั่งกําหนดคาของตัวแปร
อินสแตนทลงไปเมื่อไรก็ตามที่มีการสรางอินสแตนทใหมของคลาส Vehicle ดวยคําสั่ง
Vehicle myCar = new Vehicle(); คําสั่งกําหนดคาตัวแปรอินสแตนทที่อยูในคอนสตรัคเตอรจะ
ทํางานทันที อันที่จริงคอนสตรัคเตอรก็เหมือนกับ method ทั่วไป คําสั่งที่อยูในบลอคปกกาไมจําเปนตอง
เปนคําสั่งกําหนดคาตัวแปรคลาสเสมอไป จะเปนคําสั่งอยางอื่นก็ได คําสั่งเหลานี้จะทํางานทุกครั้งที่มีการ
สรางอินสแตนทใหมใหคลาส ตัวอยางเชน
จากตัวอยางในบรรทัด (1) เราเติมคําสั่งใหโปรแกรมแสดงผลออกนอกจอวา A car has been
built ดังนั้นคําสั่งนี้จะถูกใชงานเมื่อมีการสราง instance myCar ขึ้น ซึ่งเกิดขึ้นกอนการแสดงจํานวนลอ
class Vehicle {
int numberOfWheels;
boolean hasEngine;
Vehicle() {
numberOfWheels = 6;
hasEngine = true;
System.out.println("A car has been built."); //(1)
}
void run(){
System.out.println("I am running");
}
}
public class BuildACar2 {
public static void main (String[] args) {
Vehicle myCar = new Vehicle();
System.out.println("My car has " + myCar.numberOfWheels + "wheels.");
System.out.println("That my car has an engine is " + myCar.hasEngine + ".");
}
}
ผลลัพธคือ
A car has been built.
My car has 6wheels.
That my car has an engine is true.
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 194
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
คอนสตรัคเตอรเปนmethod ดังนั้นคอนสตรัคเตอรสามารถสงผานตัวแปรไดดวย เชน
class Vehicle {
int numberOfWheels;
boolean hasEngine;
Vehicle() {
numberOfWheels = 6;
hasEngine = true;
System.out.println("A car has been built.");
}
Vehicle(int number, boolean engine) { // (1)
numberOfWheels = number;
hasEngine = engine;
System.out. println("A car has been built.");
}
void run(){
System.out.println("I am running");
}
}
public class BuildACar3 {
public static void main (String[] args) {
Vehicle myCar = new Vehicle(4,true); //(2)
System.out.println("My car has " + myCar.numberOfWheels + "wheels.");
System.out.println("That my car has an engine is " + myCar.hasEngine + ".");
}
}
ผลลัพธคือ
A car has been built.
My car has 4wheels.
That my car has an engine is true.
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 195
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
ในตัวอยางนี้เราเพิ่มคอนสตรัคเตอรที่มีการสงผานตัวแปรในบรรทัด (1) ซึ่งเปนการโอเวอร
โหลดคอนสตรัสเตอรที่มีอยูเดิมในบรรทัด (2) เราสรางอินสแตนทโดยใชคอนสตรัคเตอรตัวใหม ซึ่งมี
การสงผานตัวแปรดวย ผลที่ไดก็คือตัวแปรอินสแตนททั้งสองจะมีคาเหมือนกับตัวแปรที่เราสงผาน
รถยนตมี 4 ลอแทนที่จะมี 6 ลอ เราเรียกคอนสตรัคเตอรที่ไมมีการสงผานตัวแปรใดๆ วา คอน
สตรัสเตอรปกติ และเรียกคอนสตรัคเตอรที่มีการสงผานตัวแปรวา คอนสตรัคเตอรโอเวอรโหลด
This() กับ constructor
ภายในคอนสตรัคเตอรเราสามารถเรียกคอนสตรัคเตอรตัวอื่นในคลาสเดียวกันไดดวยการใช
คําสั่ง this() ดังตัวอยางตอไปนี้
class A {
int a; // (1)
A() {
a = 0;
System.out.println("Default Constructor");
}
A(int i) { // (2)
this();
a = i;
System.out.println("Constructor 1");
}
A(int i,int j) { // (3)
this(i+j);
System.out.println("Constructor 2");
}
}
public class TestThis4 {
public static void main(String[] args) {
System.out.println("Instantiate x");
A x = new A();
System.out.println("variable a is " + x.a);
System.out.println("Instantiate y");
A y = new A(5);
System.out.println("variable a is " + y.a);
System.out.println("Instantiate z");
A z = new A(5,6);
System.out.println("variable a is " + z.a);
}
}
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 196
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
จากตัวอยางและผลลัพธที่ได คลาส A มีสามคอนสตรัคเตอร คอนสตรัสเตอรแรกเปนคอน
สตรัสเตอรปกติในบรรทัด (1) กําหนดคาใหตัวแปรคลาส a เปนศูนย คอนสตรัคเตอรที่หนึ่งในบรรทัด
(2) มีการรับตัว แปร i และ มีการเรียกคอนสตรัคเตอรปกติดวยคําสั่ง this() กอนที่จะเปลี่ยนคาตั้งตนของa
ใหเทากับตัวแปร i สวนคอนสตรัคเตอรตัวสุดทายคือคอนสตรัคเตอรที่สองในบรรทัด (3) มีการเรียกคอน
สตรัสเตอรที่หนึ่งดวยคําสั่ง this(i+j) มันจะสงผานคา i+j ไปให a และเนื่องจากมันเรียกคอนสตรัคเตอรที่
หนึ่งซึ่งเรียกคอนสตรัคเตอรปกติ คอนสตรัคเตอร ปกติจึงถูกเรียกไปดวย
***คําสั่ง this() ใชไดภายในคอนสตรัคเตอรเทานั้นและตองเปนคําสั่งแรกสุดเสมอ***
ตัวอยาง การใชงาน this กับ constructor
class TestThis5 {
double r , i;
TestThis5(){ //(1)
this (0.0 , 0.0);
}
TestThis5(double r , double i){//(2)
this.r = r ;
this.i = i;
}
TestThis5(TestThis5 t) {//(3)
this(t.r,t.i);
}
ผลลัพธคือ
Instantiate x
Default Constructor
variable a is 0
Instantiate y
Default Constructor
Constructor 1
variable a is 5
Instantiate z
Default Constructor
Constructor 1
Constructor 2
variable a is 11
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 197
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
คลาส TestThis5 ในตัวอยางนี้มี constructor อยู 3 ตัว โดยมีเพียงตัวที่สองเทานั้นที่รับ
พารามิเตอรเขามาและทําการกําหนดคาใหแก fields จริงๆ สวน constructor ตัวแรกและตัวที่สามมีการ
เรียก this() ในลักษณะเปน method พรอมกับสง arguments เปนคาสองคาให การใช this ในลักษณะนี้
คือการเรียก constructor ของคลาสที่มีพารามิเตอรตรงกับ arguments จาก constructors อื่นในคลาสนั้น
คอมไพเลอรจะเปนผูเลือกวามี constructor ใดมีพารามิเตอรตรงกับ arguments ที่สงใหในการเรียก this()
สําหรับในตัวอยางนี้ constructor ตัวที่ถูกเลือกคือ ตัวที่สอง แสดงวา constructor ตัวแรกและตัวที่สาม
เรียก constructor ตัวที่สองพรอมกับสงคาใหนั่นเอง
ตัวอยางแสดง การใชงาน this() ที่ทําใหเกิด error
void add(TestThis4 t){
r+=t.r ;
i += t.i;
}
void print(){
System.out.println(r + " + i " + i);
}
}
public class Flower {
int petalCount = 0;
String s = new String("null");
Flower(int petals) {
petalCount = petals;
System.out.println("Constructor w/ int arg only, petalCount= " +
petalCount);
}
Flower(String ss) {
System.out.println("Constructor w/ String arg only, s=" + ss);
s = ss;
}
Flower(String s, int petals) {
this(petals);
//! this(s); // Can't call two! ( 1 )
this.s = s; // Another use of "this" (2)
System.out.println("String & int args");
}
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 198
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
เราสามารถเรียก constructor ใน constructor โดยใช this () ไดเพียงครั้งเดียว ไมสามารถเรียกใช
งานครั้งที่สองได ดังเชนใน บรรทัดที่ (1) หากเอาเครื่องหมาย // ออก จะทําใหเกิด error
จากตัวอยางประกาศตัวแปร s ใน constructor Flower(String s, int petals) ซึ่งอาจทําให
compiler สับสนได จึงจําเปนตองใช this.s เพื่ออางถึง data member ใน class Flower และ s แทนชื่อตัว
แปรของ argument ดังในบรรทัดที่ (2)
ใน method print() เราไมสามารถเรียก ใชงาน constructor จาก method อื่นๆ ได ดังในหมายเลข
(3) หากนําเครื่องหมาย // ออกจะทําใหเกิด error
Super
เมื่อตองการเรียกคอนสตรัคเตอรของซุปเปอรคลาสใหทํางาน สามารถทําไดโดยใชคียเวิรด
super โดยมีขอกําหนดวา การเรียกใชงานคอนสตรัคเตอรของซุปเปอรคลาสจะตองทําการเรียกที่บรรทัด
แรกสุดของคอนสตรัคเตอรนั้นๆ เทานั้น
Flower() {
this("hi", 47);
System.out.println("default constructor (no args)");
}
void print() {
//! this(11); // Not inside non-constructor! (3)
System.out.println("petalCount = " + petalCount + " s = "+ s);
}
public static void main(String[] args) {
Flower x = new Flower();
x.print();
}
}
ผลลัพธคือ
Constructor w/ int arg only, petalCount= 47
String & int args
default constructor (no args)
petalCount = 47 s = hi
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 199
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
ตัวอยาง โปรแกรมการใชงานคียเวิรด this และ super
class A{
int i;
A( ){System.out.println("constructor A");}
}
class B extends A{
int i;
B(){
super();//default เรียกใช constructor ของ super
System.out.println("constructor B()");
}
B(int a,int b){
super.i = a;
this.i = b;
System.out.println("constructor B(int a, int b)");
}
void printB(){
System.out.println(" super = " + super.i);
System.out.println(" sub = " + this.i);
}
}
public class testSuper{
public static void main(String args[]){
B subB = new B(9,10);
subB.printB();
}
}
ผลลัพธที่ไดคือ
constructor A
constructor B(int a,int b)
super = 9
sub = 10
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 200
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
● ใน constructor ทุกตัวนั้นที่ Statement แรกจะตองระบุ constructor อื่นๆ ที่อยูใน class หรือ
superclass เสมอ หากไมระบุ compiler จะใส empty constructor ของ superclass ใหโดย
อัตโนมัติ
โปรแกรมที่สราง compiler สรางให
● ถา superclass ไมมี empty constructor แลว หากใน subclass ทําการเรียก super(); จะเกิด compile
error
โปรแกรมที่สราง compiler สรางให
public class A {
public A(int i){
}
}
class B extends A {
public B(){
}
}
public class A {
public A(int i){
}
}
class B extends A {
public B(){
super(); //Compiler จัดให
// Compile error
// แกโดย super(13);
}
}
=
public class A {
public A( ){
}
}
class B extends A {
public B( ){
}
}
public class A {
public A(){
}
}
class B extends A {
public B(){
super(); //Compiler จัดให
}
}
=
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 201
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
เมธอด instanceof
ใชสําหรับเปรียบเทียบวา Object นั้นๆสืบทอดมาจาก Class นั้นๆหรือไม
ตัวอยาง การใชงานเมธอด instanceof กับ คลาสที่มีการสืบทอด
class A { }
class B extends A { }
class Test{
public static void main (String [] args) {
A a = new B();
B b = new B();
A c = new A();
//B c = new A(); error
System.out.println("a is instance of A = " + (a instanceof A));
System.out.println("a is instance of B = " + (a instanceof B));
System.out.println("b is instance of A = " + (b instanceof A));
System.out.println("b is instance of B = " + (b instanceof B));
System.out.println("c is instance of A = " + (c instanceof A));
System.out.println("c is instance of B = " + (c instanceof B));
}
}
ผลลัพธที่ไดคือ
a is instance of A = true
a is instance of B = true
b is instance of A = true
b is instance of B = true
c is instance of A = true
c is instance of B = false
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 202
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
• นอกจากการสืบทอดแลว instance ยังใชกับการ implement ไดอีกดวย
ตัวอยาง การใชงานเมธอด instanceof กับ interface ซึ่งจะกลาวในหัวขอถัดไป
interface Foo { }
class Bar implements Foo { }
class TestBar {
public static void main (String [] args) {
Bar b = new Bar();
if ( b instanceof Bar) {
System.out.println("b is a Bar");
}
if (b instanceof Foo) {
System.out.println("b is a Foo");
}
}
}
ผลลัพธที่ไดคือ
b is a Bar
b is a Foo
การสืบทอดคุณสมบัติของคลาสที่มีมากกวา 2 ระดับ
Class A
Class B
Class C
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 203
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
ตัวอยาง โปรแกรมที่ไดจากรูปคือ
class A{
A(){
System.out.println("Print from A");
}
}
class B extends A{
B(){
System.out.println("Print from B");
}
}
class C extends B{
C(){
System.out.println("Print from C");
}
}
class testInherit5{
public static void main(String args[]){
C subC = new C();
}
}
ผลลัพธที่ไดคือ
Print from A
Print from B
Print from C
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 204
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
แบบฝกหัด
1. ถากําหนดใหคลาส Dog มีโครงสรางดังนี้
class Dog {
Dog(String name) { }
}
แลวคลาส Beagle สืบทอด(inherited)คุณสมบัติจากคลาส Beagle มีเพียง หนึ่ง constructor ตอไปนี้ที่
สามารถเปน constructor ในคลาส Beagle คือขอใด เพราะเหตุใด
A. Beagle() { }
B. Beagle() { super(); }
C. Beagle() { super("fido"); }
D. No constructor, allow the default constructor
2. จากคลาส Foo ที่กําหนดใหตอไปนี้
class Foo {
String doStuff(int x) { return "hello"; }
}
ขอใดตอไปนี้ไมสามารถเปน subclass ของ class Foo ได พรอมแสดงเหตุผลทุกขอ
A. String doStuff(int x) { return "hello"; }
B. int doStuff(int x) { return 42; }
C. public String doStuff(int x) { return "Hello"; }
D. protected String doStuff(int x) { return "Hello"; }
E. String doStuff(String s) { return "Hello"; }
F. int doStuff(String s) { return 42; }
3. แสดงผลลัพธที่ไดจากโปรแกรมนี้เมื่อไมเกิด error หรือหากเกิด error ใหแสดงเหตุผลที่เกิด
ขอผิดพลาดดังกลาวพรอมวิธีการแกปญหา
class ParentClass {
public int doStuff(int x) {
return x * 2;
}
}
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 205
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
public class ChildClass extends ParentClass {
public static void main(String [] args ) {
ChildClass cc = new ChildClass();
long x = cc.doStuff(7);
System.out.println("x = " + x);
}
public long doStuff(int x) {
return x * 3;
}
}
4. ผลลัพธที่ไดจากการรันโปรแกรมนี้คือ
class A {
public void baz() {
System.out.println("A");
}
}
public class B extends A {
public static void main(String [] args) {
A a = new B();
a.baz();
}
public void baz() {
System.out.println("B");
}
}
5. จากโปรแกรมที่ใหตอไปนี้ใหแสดงผลลัพธที่ไดจากการรัน
public class TestPoly {
public static void main(String [] args ){
Parent p = new Child();
}
}
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 206
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
class Parent {
public Parent() {
super();
System.out.println("instantiate a parent");
}
}
class Child extends Parent {
public Child() {
System.out.println("instantiate a child");
}
}
6. จากโปรแกรมตอไปนี้ผลลัพธที่ไดคือ
public class ThreeConst {
public static void main(String [] args) {
new ThreeConst(4L);
}
public ThreeConst(int x) {
this();
System.out.print(" " + (x * 2));
}
public ThreeConst(long x) {
this((int) x);
System.out.print(" " + x);
}
public ThreeConst() {
System.out.print("no-arg ");
}
}
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 207
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
7. จากโปรแกรมตอไปนี้ผลลัพธที่ไดคือ
class Super {
public Integer getLenght() { return new Integer(4); }
}
public class Sub extends Super {
public Long GetLenght() { return new Long(5); }
public static void main(String[] args) {
Super sooper = new Super();
Sub sub = new Sub();
System.out.println(sooper.getLenght().toString() + “,” + sub.getLenght().toString() );
}
}
8. ใหนิสิตทําการเขียนโปรแกรมดังตอไปนี้ แลวหาผลลัพธที่ไดพรอมอธิบายที่มาของผลลัพธดังกลาว
class Person {
protected String name;
public Person() { }
public Person(String n) { this.setName(n); }
public void setName(String n) { name = n; }
public String getName() { return name; }
public void printDetails() {
System.out.println("n** Details of a Person **");
System.out.println("name :: "+this.getName());
}
}
class Employee extends Person {
protected double salary;
public Employee(String n, double s) {
super(n);
this.setSalary(s);
}
บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 208
เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง
อ.สุรางคนา ระวังยศ
public void setSalary(double s) { salary = s; }
public String getSalary() {
Double d = new Double(salary);
String str = d.toString();
return str;
}
public void printDetails() {
super.printDetails();
System.out.println("salary :: "+this.getSalary());
}
}
class TestInheritance {
public static void main(String[] args) {
Person jenny = new Person("Jennifer");
Employee joey = new Employee("Joey", 200.0);
Employee judy = new Employee("Judith", 550.0);
System.out.println("*************************");
jenny.printDetails();
joey.printDetails();
judy.printDetails();
System.out.println("*************************");
}
}

Weitere ähnliche Inhalte

Mehr von Theeravaj Tum

Javacentrix com chap11-2
Javacentrix com chap11-2Javacentrix com chap11-2
Javacentrix com chap11-2Theeravaj Tum
 
Javacentrix com chap11-1
Javacentrix com chap11-1Javacentrix com chap11-1
Javacentrix com chap11-1Theeravaj Tum
 
Javacentrix com chap10-0
Javacentrix com chap10-0Javacentrix com chap10-0
Javacentrix com chap10-0Theeravaj Tum
 
Javacentrix com chap09-0
Javacentrix com chap09-0Javacentrix com chap09-0
Javacentrix com chap09-0Theeravaj Tum
 
Javacentrix com chap08-0
Javacentrix com chap08-0Javacentrix com chap08-0
Javacentrix com chap08-0Theeravaj Tum
 
Javacentrix com chap07-0
Javacentrix com chap07-0Javacentrix com chap07-0
Javacentrix com chap07-0Theeravaj Tum
 
Javacentrix com chap06-0
Javacentrix com chap06-0Javacentrix com chap06-0
Javacentrix com chap06-0Theeravaj Tum
 
Javacentrix com chap04-0
Javacentrix com chap04-0Javacentrix com chap04-0
Javacentrix com chap04-0Theeravaj Tum
 
Javacentrix com chap03-0
Javacentrix com chap03-0Javacentrix com chap03-0
Javacentrix com chap03-0Theeravaj Tum
 
Javacentrix com chap02-0
Javacentrix com chap02-0Javacentrix com chap02-0
Javacentrix com chap02-0Theeravaj Tum
 
Javacentrix com chap01-0
Javacentrix com chap01-0Javacentrix com chap01-0
Javacentrix com chap01-0Theeravaj Tum
 
Javacentrix com chap05-0
Javacentrix com chap05-0Javacentrix com chap05-0
Javacentrix com chap05-0Theeravaj Tum
 
บทที่ 13 การดักจับเ
บทที่ 13 การดักจับเบทที่ 13 การดักจับเ
บทที่ 13 การดักจับเTheeravaj Tum
 
บทที่ 12 กราฟฟิก
บทที่ 12 กราฟฟิกบทที่ 12 กราฟฟิก
บทที่ 12 กราฟฟิกTheeravaj Tum
 
บทที่ 11 การดักจับข
บทที่ 11 การดักจับขบทที่ 11 การดักจับข
บทที่ 11 การดักจับขTheeravaj Tum
 
บทที่ 7 แพ็คเกจ
บทที่ 7 แพ็คเกจบทที่ 7 แพ็คเกจ
บทที่ 7 แพ็คเกจTheeravaj Tum
 
บทที่ 6 อาร์เรย์
บทที่ 6 อาร์เรย์บทที่ 6 อาร์เรย์
บทที่ 6 อาร์เรย์Theeravaj Tum
 
บทที่ 5 คลาส
บทที่ 5 คลาสบทที่ 5 คลาส
บทที่ 5 คลาสTheeravaj Tum
 
บทที่ 3 คำสั่งควบค
บทที่ 3 คำสั่งควบคบทที่ 3 คำสั่งควบค
บทที่ 3 คำสั่งควบคTheeravaj Tum
 
บทที่ 2 ชนิดของตัว
บทที่ 2 ชนิดของตัวบทที่ 2 ชนิดของตัว
บทที่ 2 ชนิดของตัวTheeravaj Tum
 

Mehr von Theeravaj Tum (20)

Javacentrix com chap11-2
Javacentrix com chap11-2Javacentrix com chap11-2
Javacentrix com chap11-2
 
Javacentrix com chap11-1
Javacentrix com chap11-1Javacentrix com chap11-1
Javacentrix com chap11-1
 
Javacentrix com chap10-0
Javacentrix com chap10-0Javacentrix com chap10-0
Javacentrix com chap10-0
 
Javacentrix com chap09-0
Javacentrix com chap09-0Javacentrix com chap09-0
Javacentrix com chap09-0
 
Javacentrix com chap08-0
Javacentrix com chap08-0Javacentrix com chap08-0
Javacentrix com chap08-0
 
Javacentrix com chap07-0
Javacentrix com chap07-0Javacentrix com chap07-0
Javacentrix com chap07-0
 
Javacentrix com chap06-0
Javacentrix com chap06-0Javacentrix com chap06-0
Javacentrix com chap06-0
 
Javacentrix com chap04-0
Javacentrix com chap04-0Javacentrix com chap04-0
Javacentrix com chap04-0
 
Javacentrix com chap03-0
Javacentrix com chap03-0Javacentrix com chap03-0
Javacentrix com chap03-0
 
Javacentrix com chap02-0
Javacentrix com chap02-0Javacentrix com chap02-0
Javacentrix com chap02-0
 
Javacentrix com chap01-0
Javacentrix com chap01-0Javacentrix com chap01-0
Javacentrix com chap01-0
 
Javacentrix com chap05-0
Javacentrix com chap05-0Javacentrix com chap05-0
Javacentrix com chap05-0
 
บทที่ 13 การดักจับเ
บทที่ 13 การดักจับเบทที่ 13 การดักจับเ
บทที่ 13 การดักจับเ
 
บทที่ 12 กราฟฟิก
บทที่ 12 กราฟฟิกบทที่ 12 กราฟฟิก
บทที่ 12 กราฟฟิก
 
บทที่ 11 การดักจับข
บทที่ 11 การดักจับขบทที่ 11 การดักจับข
บทที่ 11 การดักจับข
 
บทที่ 7 แพ็คเกจ
บทที่ 7 แพ็คเกจบทที่ 7 แพ็คเกจ
บทที่ 7 แพ็คเกจ
 
บทที่ 6 อาร์เรย์
บทที่ 6 อาร์เรย์บทที่ 6 อาร์เรย์
บทที่ 6 อาร์เรย์
 
บทที่ 5 คลาส
บทที่ 5 คลาสบทที่ 5 คลาส
บทที่ 5 คลาส
 
บทที่ 3 คำสั่งควบค
บทที่ 3 คำสั่งควบคบทที่ 3 คำสั่งควบค
บทที่ 3 คำสั่งควบค
 
บทที่ 2 ชนิดของตัว
บทที่ 2 ชนิดของตัวบทที่ 2 ชนิดของตัว
บทที่ 2 ชนิดของตัว
 

บทที่ 8 คุณสมบัติก

  • 2. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 182 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ เนื้อหาบทเรียน ♦ การสืบสกุล(Inheritance) ♦ คียเวิรด This ♦ คียเวิรด Super ♦ คียเวิรด Instanceof ♦ การสืบทอดคุณสมบัติของคลาสที่มากกวา 2 ขั้น
  • 3. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 183 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ Parent Son Super Class Sub Class A B C Method B Method C Method A การสืบทอด(Inheritance) เราสามารถสรางคลาสใหมโดยอาศัยคลาสที่มีอยูแลวเปนตนแบบ เราเรียกคลาสใหมวา สับคลาส (sub class) ของคลาสเกา และเรียกคลาสเกาวา ซูปเปอรคลาส(Supper class) ของคลาสใหม ตัวแปร คลาสและ method จะไดรับการสืบทอดไปยังสับคลาสโดยอัตโนมัติ เหมือนกับการสืบทอดลักษณะทาง พันธุกรรมจากพอไปสูลูก ในภาษาจาวาจะยอมใหซับคลาสสืบทอด(inherited)คุณสมบัติไดจากซุปเปอรคลาสไดเพียงคลาส เดียวเทานั้น ซึ่งไมเหมือนกับภาษา C++ ที่ซับคลาสสามารถสืบทอดคุณสมบัติไดจากหลายซุปเปอร คลาส กลาวไดวาคุณสมบัติการสืบทอด(Inheritance) คือการที่ Class หนึ่งๆสามารถสืบทอดคุณสมบัติ บางประการจาก Class อื่น แลวเพิ่มคุณสมบัติเฉพาะของ Class นั้นเขาไป Class ที่ไดรับการสืบทอด คุณสมบัติเรียกวา Subclasses สวน Class ที่เปนตนแบบเรียกวา Superclass ประโยชนของคุณสมบัติการ สืบทอดคือ เปนการชวยใหไมตองออกแบบ พัฒนา สวนที่ซ้ําหลายๆรอบ(reusable) Class หนึ่งๆจะมี Superclass ไดเพียง Class เดียวเทานั้น (Single Inheritance) ดังรูป รูปแบบของการประกาศการสืบทอดคุณสมบัติของคลาส class subclass_name extends superclass_name{ [member;] }
  • 4. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 184 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ ตัวอยาง โปรแกรมที่มีคุณสมบัติการสืบทอด class A{ void printA(){ System.out.println("A"); } } class B extends A{ void printB(){ System.out.println("B"); } } class TestInherit1{ public static void main(String args[]){ A x = new A(); x.printA(); B y = new B(); y.printA(); y.printB(); } } ผลลัพธที่ได A A B ตัวอยาง โปรแกรมที่มีคุณสมบัติการสืบทอด class AA{ int i,j; void printA() { System.out.println(" i = " + i + " : j = " + j); }}
  • 5. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 185 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ class BB extends AA{ int k; void printB(){ System.out.println(" k = " + k); } void sum( ) { System.out.println("i+j+k="+(i+j+k)); } } class TestInherit2{ public static void main(String args[]){ AA superClass = new AA(); BB subClass = new BB(); System.out.println("print from superclass"); superClass.i = 10; superClass.j = 20; superClass.printA(); System.out.println(); System.out.println("print from subclass"); subClass.i = 3; subClass.j = 4; subClass.k = 5; subClass.printA(); subClass.printB(); subClass.sum(); } } ผลลัพธที่ไดคือ print from superclass i = 10 : j = 20 print from subclass i = 3 : j = 4 k = 5 i+j+k=12
  • 6. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 186 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ ตัวอยาง โปรแกรมที่มีการเรียกใชคลาสที่มีการสืบทอด class TestInherit3{ static void methodA(A a){ a.printA(); } static void methodB(B b){ b.printB(); } public static void main(String args[]){ A x = new A(); methodA(x); B y = new B(); methodA(y); methodB(y); A z = new B(); // super : sub z.printA(); //z.printB(); } } /*method ที่รับ instance ของคลาสแมเปนพารามิเตอรจะสามารถรับ instance ของ class ลูกเปน parameter ไดดวย*/ ผลลัพธที่ไดคือ A A B A หมายเหตุ : หากตองการปองกันการเขาถึงdata member(attribute และ method)ของ super class ใหใส สวนขยายหนา data member ดวยคําวา private ตามนิยามของ Sun แบง ความสัมพันธระหวาง Classes เปนสองลักษณะคือ – IS-A เปนความสัมพันธที่ Class หนึ่งเปน Subclass ของอีก Class หนึ่ง – HAS-A เปนความสัมพันธที่ Class หนึ่งเปนสวนประกอบ ของอีก Class หนึ่ง
  • 7. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 187 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ ตัวอยางการนําคุณสมบัติการสืบทอดมาประยุกตใชในการเขียนโปรแกรม เชน คลาส Vehicle นิยามสิ่งที่ใชตัดสินวาวัตถุที่จัดวาเปนรถยนตตองมีคุณสมบัติและพฤติกรรมอะไรบาง คราวนี้ถาเรา ตองการสรางนิยามที่มีความเฉพาะเจาะจงมากขึ้น เชนนิยามของรถบรรทุก นิยามของรถเกง เราอาจสราง คลาสใหมชื่อ Truck กับ PrivateCar ซึ่งนิยามคุณสมบัติและพฤติกรรมที่มีเฉพาะแตในรถบรรทุก และรถเกง มีความสัมพันธกันดังรูป แทนที่เราจะสรางคลาสทั้งสองขึ้นมาใหมตั้งแตตน เราอาจใชคลาส Vehicle เปนตนแบบเพราะ ทั้งรถบรรทุก และรถเกงยอมตองมีลอ มีเครื่อง และวิ่งได จากนั้นคอยเติมคุณสมบัติและพฤติกรรมอื่นๆ ที่ มีเฉพาะในรถบรรทุก หรือรถเกงเขาไป เราทําเชนนี้ไดโดยการสรางสับคลาสของซูปเปอรคลาส Vehicle สองตัวชื่อ Truck และ PrivateCar ดังตัวอยางตอไปนี้ vehicle Truck PrivateCar class Vehicle { int numberOfWheels; boolean hasEngine; void run(){ System.out.println("I am running."); } } class Truck extends Vehicle { // (1) float maximumLoad; // (2) void load(float weight) { // (3) if (weight <= maximumLoad) System.out.println("I am carrying a " + weight + "-pound load."); } } }
  • 8. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 188 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ ในบรรทัด (1),(4) เราประกาศคลาสใหมชื่อ Truck และ PrivateCar ซึ่งเปนสับคลาสของคลาส Vehicle ที่มีอยูแลว โดยเราใชคําสั่ง extends ตามดวยชื่อซูปเปอรคลาส สิ่งที่ไดมาโดยอัตโนมัติคือทั้ง คลาส Truck และ PrivateCar จะมีตัวแปรชื่อ noOfWheels, hasEngine และมีmethodชื่อ run() พวงมาดวย ทันทีจากนั้นเราสามารถสรางตัวแปรคลาสและmethodเพิ่มเติมได เพื่อใชเปนสิ่งที่บอกลักษณะที่มีเฉพาะ แตในรถบรรทุกหรือรถเกง ในบรรทัด(2)เราสรางตัวแปร maximumLoad ใหคลาส Truck เพื่อใชในระบุ น้ําหนักบรรทุกสูงสุดของรถบรรทุก และสรางmethod load() ในบรรทัด (3) เพราะสิ่งที่รถบรรทุกตองทํา ไดคือการบรรทุกของในบรรทัด (5) เราสรางตัวแปร numberOfPassengers ใหคลาส PrivateCar เพื่อใช ระบุจํานวนผูนั่ง รถเกงควรมีเครื่องเลนซีดีดวย เพื่อใหเกิดความแตกตางกับรถบรรทุก ดังนั้นเราจึงสราง method playCD() ในบรรทัด (6) คําสั่งในmethod main() เปนการสรางอินสแตนทใหกับคลาส Truck และ PrivateCar อยางละ หนึ่งอินสแตนท สังเกตวาอินสแตนททั้งสองมีตัวแปร numberOfWheels และmethod run()ทั้งที่ไมได class PrivateCar extends Vehicle { // (4) int numberOfPassengers; // (5) void playCD() { // (6) System.out.println("CD is playing."); } } public class BuildACar4 { public static void main(String[] args) { Truck isuzu = new Truck(); PrivateCar toyota = new PrivateCar(); isuzu.numberOfWheels = 6; toyota.numberOfWheels = 4; isuzu.maximumLoad = 1500.00F; toyota.numberOfPassengers = 5; isuzu.load(700.0F); isuzu.run(); toyota.playCD(); toyota.run(); } } ผลลัพธคือ I am carrying a 700.0-pound load. I am running. CD is playing. I am running.
  • 9. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 189 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ สรางไวในคลาส ที่เปนเชนนี้เพราะคลาสทั้งสองสืบทอดคุณลักษณะของคลาส Vehicle ผลการรัน โปรแกรมขางตนจะเปนดังผลลัพธที่แสดง เราสามารถสรางสับคลาสของสับคลาสไดดวย ดังนั้นคุณลักษณะของคลาสสามารถสืบทอดตอ กันไปไดเรื่อยๆ ไมมีที่สิ้นสุด คลาสคลาสหนึ่งมีไดหลายสับคลาสเชนในกรณีของคลาส Vehicle มีสอง สับคลาสคือ Truck และ PrivateCar แตคลาสคลาสหนึ่งในภาษาจาวามีได แคซุปเปอรคลาสเดียว กลาวคือเมื่อ Truck สืบทอดคุณลักษณะจากซุปเปอรคลาส Vehicle แลว คลาส Truck ไมสามารถสืบทอด คุณลักษณะจากคลาสอื่นไดอีก คําสั่ง extends จึงตามดวยชื่อซุปเปอรคลาสไดแคซุปเปอรคลาสเดียว เทานั้น Key word : this ในการเขียนโปรแกรมเพื่อสราง class บางครั้งอาจเกิดปญหาตัวแปรคลาส กับ ตัวแปรทองถิ่นใน method ในคลาสเดียวกัน สามารถมีชื่อซ้ํากันได เพราะตัวแปรคลาสเกิดขึ้นเมื่อมีการสราง instance แตตัว แปรทองถิ่นเกิดขึ้นเมื่อมีการเรียกใช method และตายไปทันทีที่ method รันเสร็จ จาวาจึงแยกแยะความ แตกตางระหวางตัวแปรทั้งสองตัวไดแตบางครั้งก็เกิดการสับสน คําสั่ง this จึงมีไวแยกแยะความแตกตาง ใหชัดเจนไปเลย ตัวอยางเชน class TestThis1 { int a; // (1) float b; // (2) char c; // (3) void x(int a, float b,char i){ // (4) char c; // (5) this.a = a; // (6) c = i; // (7) this.y(); // (8) y(); // (9) } void y() { // (10) System.out.println("Hello World"); } }
  • 10. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 190 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ คลาสนี้มีตัวแปรคลาสสามตัวไดแก a , b และ c ในบรรทัด (1)(2)(3) method x() มีการสงผาน ตัวแปรที่มีชื่อเหมือนตัวแปรคลาส a และ b ในบรรทัด (4) อีกทั้งยังประกาศตัวแปรภายในmethod ชื่อ c ซึ่งซ้ํากับตัวแปรคลาสอีก ในบรรทัด (5) คําสั่งในบรรทัด (6) ใชคําสั่ง this ตามดวยจุดนําหนา a เปนการ ชี้เฉพาะเจาะจงลงไปวา หมายถึงตัวแปรคลาส a ที่ประกาศไวในบรรทัด (1) คําสั่งนี้เปนการกําหนดคาตัว แปรคลาส a ใหมีคาเทากับตัวแปรสงผาน a ซึ่งอยูหลังเครื่องหมายเทากับ ตัวแปรสงผานไมมีคําวา this นําหนาคําสั่งในบรรทัด (7) เปนการอางถึงตัวแปร c ที่ประกาศไวในบรรทัด (5) เพราะไมมี this นําหนา สรุปก็คือ ถามีการใชชื่อซ้ํากัน การใชชื่อตัวแปรเฉยๆ จะถือวาเปนตัวแปรภายใน method ถาตองการอาง ถึงตัวแปรคลาสตองระบุ this ดวยเสมอ แตถาไมมีการใชชื่อซ้ํากัน ไมตองระบุ this ก็ไดเหมือนกันที่เรา เคยเขียนกัน คําสั่ง this ใชระบุเฉพาะเจาะจงไดดวยวาหมายถึง method ในคลาสเดียวกันดังที่ใชใน บรรทัด (8) แตเนื่องจากไมมีความสับสนในกรณีของ method อยูแลว (เพราะไมมี method ทองถิ่น) การ ระบุ this จึงไมจําเปนสําหรับการเรียก method บรรทัด (8) กับ บรรทัด(9) จึงมีความหมายเหมือนกัน ตัวอยาง การใช keyword this แตถาเอาเครื่องหมาย // บรรทัดที่ (1) ออกแลวใสเครื่องหมาย // หนาบรรทัดที่(2) แทน ผลลัพธ จะกลายเปน Pokemon แทน class TestThis2 { String name = "Pokemon"; TestThis2(String name){ //name = name; // (1) this.name = name ;//(2) } void print(){ System.out.println(name); } public static void main(String[] args) { TestThis2 t = new TestThis2("Sompong"); t.print(); } } ผลลัพธคือ Sompong
  • 11. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 191 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ ตัวอยาง การใช keyword this คลาส TestThis3 ในตัวอยางนี้มี field r และ i และมี constructor รับพารามิเตอรที่ชื่อ r และ i เขามา เพื่อกําหนดคาใหแก fields ที่มีชื่อเหมือนกัน ถาหากเขียนประโยคกําหนดคาเปน r = r และ i=i ก็ จะเปนการกําหนดคาใหแกตัวเองไมวาชื่อที่อางถึงนี้จะหมายถึงชื่อใด ซึ่งไมใชสิ่งที่ตองการ เราจึงตอง ใช this ชวยในการระบุวา this.r หมายถึง r ตัวที่เปนสมาชิกในคลาส สวน r เพียงตัวเดียวนั้นคือ ตัวที่ เปนพารามิเตอร สังเกตวาชื่อพารามิเตอรจะบังชื่อที่อยูขางนอก method และในทํานองเดียวกัน this.i กับ i หากใน method นั้นไมมีพารามิเตอรที่มีชื่อเหมือนกับ field ของคลาสอยางเชน add() และ print( ) ในตัวอยางนี้ การอางถึง r หรือ i จะหมายถึงตัวที่เปน field ของคลาส นอกจากนั้นภาษาจาวา ยังมีการใช this ในอีกความหมายหนึ่งคือ ใช this ในการเรียก method จะหมายถึงการเรียก constructor ของคลาสนั้น ดังตัวอยาง this( ) class TestThis3 { double r, ; TestThis3(double r, double i ){ this.r = r ; this.i = i;} public void add(TestThis3 t){ r+= t.r ; i += t.i; } void print(){ System.out.println(r + " + i " + i ); } }
  • 12. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 192 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ คงจําไดวาถาไมมีการกําหนดคาเริ่มตนของตัวแปรคลาสไว เวลาสรางอินสแตนท จาวาเวอรชัวน แมทชีน จะกําหนดคาปกติให การกําหนดคาเริ่มตนทําไดดวยการกําหนดเขาไปเลยตอนนิยามคลาส จา วามี method พิเศษชนิดหนึ่งชื่อวา คอนสตรัคเตอร ซึ่งเปน method ที่มีไวสําหรับการกําหนดคาเริ่มตน ใหกับอินสแตนทโดยเฉพาะ คอนสตรัคเตอรเปนทางเลือกอีกทางหนึ่งของการกําหนดคาใหตัวแปรคลาส ลองพิจารณาการกําหนดคาเริ่มตนใหตัวแปรคลาสดวยการใชคอนสตรัคเตอรดังตัวอยางขางลางนี้ ตัวอยาง การใชงาน constructor Method constructor คือ method ในบรรทัด (1) method constructor ตองมีชื่อเหมือนชื่อคลาส เสมอ แตตามดวย () เพื่อใหรูวาเปน method และตองไมมีคําวา void หรือชื่อชนิดของตัวแปรใดๆ class Vehicle { int numberOfWheels; boolean hasEngine; Vehicle() { // (1) numberOfWheels = 6; hasEngine = true; } void run(){ System.out.println("I am running"); } } public class BuildACar1 { public static void main (String[] args) { Vehicle myCar = new Vehicle(); System.out.println("My car has " + myCar.numberOfWheels + "wheels."); System.out.println("That my car has an engine is " +myCar.hasEngine + "."); } } ผลลัพธคือ My car has 6wheels. That my car has an engine is true.
  • 13. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 193 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ นําหนาชื่อคอนสตรัคเตอร ภายในบลอคปกกาของคอนสตรัสเตอรเราใสคําสั่งกําหนดคาของตัวแปร อินสแตนทลงไปเมื่อไรก็ตามที่มีการสรางอินสแตนทใหมของคลาส Vehicle ดวยคําสั่ง Vehicle myCar = new Vehicle(); คําสั่งกําหนดคาตัวแปรอินสแตนทที่อยูในคอนสตรัคเตอรจะ ทํางานทันที อันที่จริงคอนสตรัคเตอรก็เหมือนกับ method ทั่วไป คําสั่งที่อยูในบลอคปกกาไมจําเปนตอง เปนคําสั่งกําหนดคาตัวแปรคลาสเสมอไป จะเปนคําสั่งอยางอื่นก็ได คําสั่งเหลานี้จะทํางานทุกครั้งที่มีการ สรางอินสแตนทใหมใหคลาส ตัวอยางเชน จากตัวอยางในบรรทัด (1) เราเติมคําสั่งใหโปรแกรมแสดงผลออกนอกจอวา A car has been built ดังนั้นคําสั่งนี้จะถูกใชงานเมื่อมีการสราง instance myCar ขึ้น ซึ่งเกิดขึ้นกอนการแสดงจํานวนลอ class Vehicle { int numberOfWheels; boolean hasEngine; Vehicle() { numberOfWheels = 6; hasEngine = true; System.out.println("A car has been built."); //(1) } void run(){ System.out.println("I am running"); } } public class BuildACar2 { public static void main (String[] args) { Vehicle myCar = new Vehicle(); System.out.println("My car has " + myCar.numberOfWheels + "wheels."); System.out.println("That my car has an engine is " + myCar.hasEngine + "."); } } ผลลัพธคือ A car has been built. My car has 6wheels. That my car has an engine is true.
  • 14. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 194 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ คอนสตรัคเตอรเปนmethod ดังนั้นคอนสตรัคเตอรสามารถสงผานตัวแปรไดดวย เชน class Vehicle { int numberOfWheels; boolean hasEngine; Vehicle() { numberOfWheels = 6; hasEngine = true; System.out.println("A car has been built."); } Vehicle(int number, boolean engine) { // (1) numberOfWheels = number; hasEngine = engine; System.out. println("A car has been built."); } void run(){ System.out.println("I am running"); } } public class BuildACar3 { public static void main (String[] args) { Vehicle myCar = new Vehicle(4,true); //(2) System.out.println("My car has " + myCar.numberOfWheels + "wheels."); System.out.println("That my car has an engine is " + myCar.hasEngine + "."); } } ผลลัพธคือ A car has been built. My car has 4wheels. That my car has an engine is true.
  • 15. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 195 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ ในตัวอยางนี้เราเพิ่มคอนสตรัคเตอรที่มีการสงผานตัวแปรในบรรทัด (1) ซึ่งเปนการโอเวอร โหลดคอนสตรัสเตอรที่มีอยูเดิมในบรรทัด (2) เราสรางอินสแตนทโดยใชคอนสตรัคเตอรตัวใหม ซึ่งมี การสงผานตัวแปรดวย ผลที่ไดก็คือตัวแปรอินสแตนททั้งสองจะมีคาเหมือนกับตัวแปรที่เราสงผาน รถยนตมี 4 ลอแทนที่จะมี 6 ลอ เราเรียกคอนสตรัคเตอรที่ไมมีการสงผานตัวแปรใดๆ วา คอน สตรัสเตอรปกติ และเรียกคอนสตรัคเตอรที่มีการสงผานตัวแปรวา คอนสตรัคเตอรโอเวอรโหลด This() กับ constructor ภายในคอนสตรัคเตอรเราสามารถเรียกคอนสตรัคเตอรตัวอื่นในคลาสเดียวกันไดดวยการใช คําสั่ง this() ดังตัวอยางตอไปนี้ class A { int a; // (1) A() { a = 0; System.out.println("Default Constructor"); } A(int i) { // (2) this(); a = i; System.out.println("Constructor 1"); } A(int i,int j) { // (3) this(i+j); System.out.println("Constructor 2"); } } public class TestThis4 { public static void main(String[] args) { System.out.println("Instantiate x"); A x = new A(); System.out.println("variable a is " + x.a); System.out.println("Instantiate y"); A y = new A(5); System.out.println("variable a is " + y.a); System.out.println("Instantiate z"); A z = new A(5,6); System.out.println("variable a is " + z.a); } }
  • 16. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 196 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ จากตัวอยางและผลลัพธที่ได คลาส A มีสามคอนสตรัคเตอร คอนสตรัสเตอรแรกเปนคอน สตรัสเตอรปกติในบรรทัด (1) กําหนดคาใหตัวแปรคลาส a เปนศูนย คอนสตรัคเตอรที่หนึ่งในบรรทัด (2) มีการรับตัว แปร i และ มีการเรียกคอนสตรัคเตอรปกติดวยคําสั่ง this() กอนที่จะเปลี่ยนคาตั้งตนของa ใหเทากับตัวแปร i สวนคอนสตรัคเตอรตัวสุดทายคือคอนสตรัคเตอรที่สองในบรรทัด (3) มีการเรียกคอน สตรัสเตอรที่หนึ่งดวยคําสั่ง this(i+j) มันจะสงผานคา i+j ไปให a และเนื่องจากมันเรียกคอนสตรัคเตอรที่ หนึ่งซึ่งเรียกคอนสตรัคเตอรปกติ คอนสตรัคเตอร ปกติจึงถูกเรียกไปดวย ***คําสั่ง this() ใชไดภายในคอนสตรัคเตอรเทานั้นและตองเปนคําสั่งแรกสุดเสมอ*** ตัวอยาง การใชงาน this กับ constructor class TestThis5 { double r , i; TestThis5(){ //(1) this (0.0 , 0.0); } TestThis5(double r , double i){//(2) this.r = r ; this.i = i; } TestThis5(TestThis5 t) {//(3) this(t.r,t.i); } ผลลัพธคือ Instantiate x Default Constructor variable a is 0 Instantiate y Default Constructor Constructor 1 variable a is 5 Instantiate z Default Constructor Constructor 1 Constructor 2 variable a is 11
  • 17. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 197 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ คลาส TestThis5 ในตัวอยางนี้มี constructor อยู 3 ตัว โดยมีเพียงตัวที่สองเทานั้นที่รับ พารามิเตอรเขามาและทําการกําหนดคาใหแก fields จริงๆ สวน constructor ตัวแรกและตัวที่สามมีการ เรียก this() ในลักษณะเปน method พรอมกับสง arguments เปนคาสองคาให การใช this ในลักษณะนี้ คือการเรียก constructor ของคลาสที่มีพารามิเตอรตรงกับ arguments จาก constructors อื่นในคลาสนั้น คอมไพเลอรจะเปนผูเลือกวามี constructor ใดมีพารามิเตอรตรงกับ arguments ที่สงใหในการเรียก this() สําหรับในตัวอยางนี้ constructor ตัวที่ถูกเลือกคือ ตัวที่สอง แสดงวา constructor ตัวแรกและตัวที่สาม เรียก constructor ตัวที่สองพรอมกับสงคาใหนั่นเอง ตัวอยางแสดง การใชงาน this() ที่ทําใหเกิด error void add(TestThis4 t){ r+=t.r ; i += t.i; } void print(){ System.out.println(r + " + i " + i); } } public class Flower { int petalCount = 0; String s = new String("null"); Flower(int petals) { petalCount = petals; System.out.println("Constructor w/ int arg only, petalCount= " + petalCount); } Flower(String ss) { System.out.println("Constructor w/ String arg only, s=" + ss); s = ss; } Flower(String s, int petals) { this(petals); //! this(s); // Can't call two! ( 1 ) this.s = s; // Another use of "this" (2) System.out.println("String & int args"); }
  • 18. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 198 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ เราสามารถเรียก constructor ใน constructor โดยใช this () ไดเพียงครั้งเดียว ไมสามารถเรียกใช งานครั้งที่สองได ดังเชนใน บรรทัดที่ (1) หากเอาเครื่องหมาย // ออก จะทําใหเกิด error จากตัวอยางประกาศตัวแปร s ใน constructor Flower(String s, int petals) ซึ่งอาจทําให compiler สับสนได จึงจําเปนตองใช this.s เพื่ออางถึง data member ใน class Flower และ s แทนชื่อตัว แปรของ argument ดังในบรรทัดที่ (2) ใน method print() เราไมสามารถเรียก ใชงาน constructor จาก method อื่นๆ ได ดังในหมายเลข (3) หากนําเครื่องหมาย // ออกจะทําใหเกิด error Super เมื่อตองการเรียกคอนสตรัคเตอรของซุปเปอรคลาสใหทํางาน สามารถทําไดโดยใชคียเวิรด super โดยมีขอกําหนดวา การเรียกใชงานคอนสตรัคเตอรของซุปเปอรคลาสจะตองทําการเรียกที่บรรทัด แรกสุดของคอนสตรัคเตอรนั้นๆ เทานั้น Flower() { this("hi", 47); System.out.println("default constructor (no args)"); } void print() { //! this(11); // Not inside non-constructor! (3) System.out.println("petalCount = " + petalCount + " s = "+ s); } public static void main(String[] args) { Flower x = new Flower(); x.print(); } } ผลลัพธคือ Constructor w/ int arg only, petalCount= 47 String & int args default constructor (no args) petalCount = 47 s = hi
  • 19. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 199 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ ตัวอยาง โปรแกรมการใชงานคียเวิรด this และ super class A{ int i; A( ){System.out.println("constructor A");} } class B extends A{ int i; B(){ super();//default เรียกใช constructor ของ super System.out.println("constructor B()"); } B(int a,int b){ super.i = a; this.i = b; System.out.println("constructor B(int a, int b)"); } void printB(){ System.out.println(" super = " + super.i); System.out.println(" sub = " + this.i); } } public class testSuper{ public static void main(String args[]){ B subB = new B(9,10); subB.printB(); } } ผลลัพธที่ไดคือ constructor A constructor B(int a,int b) super = 9 sub = 10
  • 20. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 200 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ ● ใน constructor ทุกตัวนั้นที่ Statement แรกจะตองระบุ constructor อื่นๆ ที่อยูใน class หรือ superclass เสมอ หากไมระบุ compiler จะใส empty constructor ของ superclass ใหโดย อัตโนมัติ โปรแกรมที่สราง compiler สรางให ● ถา superclass ไมมี empty constructor แลว หากใน subclass ทําการเรียก super(); จะเกิด compile error โปรแกรมที่สราง compiler สรางให public class A { public A(int i){ } } class B extends A { public B(){ } } public class A { public A(int i){ } } class B extends A { public B(){ super(); //Compiler จัดให // Compile error // แกโดย super(13); } } = public class A { public A( ){ } } class B extends A { public B( ){ } } public class A { public A(){ } } class B extends A { public B(){ super(); //Compiler จัดให } } =
  • 21. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 201 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ เมธอด instanceof ใชสําหรับเปรียบเทียบวา Object นั้นๆสืบทอดมาจาก Class นั้นๆหรือไม ตัวอยาง การใชงานเมธอด instanceof กับ คลาสที่มีการสืบทอด class A { } class B extends A { } class Test{ public static void main (String [] args) { A a = new B(); B b = new B(); A c = new A(); //B c = new A(); error System.out.println("a is instance of A = " + (a instanceof A)); System.out.println("a is instance of B = " + (a instanceof B)); System.out.println("b is instance of A = " + (b instanceof A)); System.out.println("b is instance of B = " + (b instanceof B)); System.out.println("c is instance of A = " + (c instanceof A)); System.out.println("c is instance of B = " + (c instanceof B)); } } ผลลัพธที่ไดคือ a is instance of A = true a is instance of B = true b is instance of A = true b is instance of B = true c is instance of A = true c is instance of B = false
  • 22. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 202 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ • นอกจากการสืบทอดแลว instance ยังใชกับการ implement ไดอีกดวย ตัวอยาง การใชงานเมธอด instanceof กับ interface ซึ่งจะกลาวในหัวขอถัดไป interface Foo { } class Bar implements Foo { } class TestBar { public static void main (String [] args) { Bar b = new Bar(); if ( b instanceof Bar) { System.out.println("b is a Bar"); } if (b instanceof Foo) { System.out.println("b is a Foo"); } } } ผลลัพธที่ไดคือ b is a Bar b is a Foo การสืบทอดคุณสมบัติของคลาสที่มีมากกวา 2 ระดับ Class A Class B Class C
  • 23. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 203 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ ตัวอยาง โปรแกรมที่ไดจากรูปคือ class A{ A(){ System.out.println("Print from A"); } } class B extends A{ B(){ System.out.println("Print from B"); } } class C extends B{ C(){ System.out.println("Print from C"); } } class testInherit5{ public static void main(String args[]){ C subC = new C(); } } ผลลัพธที่ไดคือ Print from A Print from B Print from C
  • 24. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 204 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ แบบฝกหัด 1. ถากําหนดใหคลาส Dog มีโครงสรางดังนี้ class Dog { Dog(String name) { } } แลวคลาส Beagle สืบทอด(inherited)คุณสมบัติจากคลาส Beagle มีเพียง หนึ่ง constructor ตอไปนี้ที่ สามารถเปน constructor ในคลาส Beagle คือขอใด เพราะเหตุใด A. Beagle() { } B. Beagle() { super(); } C. Beagle() { super("fido"); } D. No constructor, allow the default constructor 2. จากคลาส Foo ที่กําหนดใหตอไปนี้ class Foo { String doStuff(int x) { return "hello"; } } ขอใดตอไปนี้ไมสามารถเปน subclass ของ class Foo ได พรอมแสดงเหตุผลทุกขอ A. String doStuff(int x) { return "hello"; } B. int doStuff(int x) { return 42; } C. public String doStuff(int x) { return "Hello"; } D. protected String doStuff(int x) { return "Hello"; } E. String doStuff(String s) { return "Hello"; } F. int doStuff(String s) { return 42; } 3. แสดงผลลัพธที่ไดจากโปรแกรมนี้เมื่อไมเกิด error หรือหากเกิด error ใหแสดงเหตุผลที่เกิด ขอผิดพลาดดังกลาวพรอมวิธีการแกปญหา class ParentClass { public int doStuff(int x) { return x * 2; } }
  • 25. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 205 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ public class ChildClass extends ParentClass { public static void main(String [] args ) { ChildClass cc = new ChildClass(); long x = cc.doStuff(7); System.out.println("x = " + x); } public long doStuff(int x) { return x * 3; } } 4. ผลลัพธที่ไดจากการรันโปรแกรมนี้คือ class A { public void baz() { System.out.println("A"); } } public class B extends A { public static void main(String [] args) { A a = new B(); a.baz(); } public void baz() { System.out.println("B"); } } 5. จากโปรแกรมที่ใหตอไปนี้ใหแสดงผลลัพธที่ไดจากการรัน public class TestPoly { public static void main(String [] args ){ Parent p = new Child(); } }
  • 26. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 206 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ class Parent { public Parent() { super(); System.out.println("instantiate a parent"); } } class Child extends Parent { public Child() { System.out.println("instantiate a child"); } } 6. จากโปรแกรมตอไปนี้ผลลัพธที่ไดคือ public class ThreeConst { public static void main(String [] args) { new ThreeConst(4L); } public ThreeConst(int x) { this(); System.out.print(" " + (x * 2)); } public ThreeConst(long x) { this((int) x); System.out.print(" " + x); } public ThreeConst() { System.out.print("no-arg "); } }
  • 27. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 207 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ 7. จากโปรแกรมตอไปนี้ผลลัพธที่ไดคือ class Super { public Integer getLenght() { return new Integer(4); } } public class Sub extends Super { public Long GetLenght() { return new Long(5); } public static void main(String[] args) { Super sooper = new Super(); Sub sub = new Sub(); System.out.println(sooper.getLenght().toString() + “,” + sub.getLenght().toString() ); } } 8. ใหนิสิตทําการเขียนโปรแกรมดังตอไปนี้ แลวหาผลลัพธที่ไดพรอมอธิบายที่มาของผลลัพธดังกลาว class Person { protected String name; public Person() { } public Person(String n) { this.setName(n); } public void setName(String n) { name = n; } public String getName() { return name; } public void printDetails() { System.out.println("n** Details of a Person **"); System.out.println("name :: "+this.getName()); } } class Employee extends Person { protected double salary; public Employee(String n, double s) { super(n); this.setSalary(s); }
  • 28. บทที่ 8 การสืบทอดคุณสมบัติของคลาส หนาที่ 208 เอกสารประกอบการสอน 305272 การเขียนโปรแกรมคอมพิวเตอรขั้นสูง อ.สุรางคนา ระวังยศ public void setSalary(double s) { salary = s; } public String getSalary() { Double d = new Double(salary); String str = d.toString(); return str; } public void printDetails() { super.printDetails(); System.out.println("salary :: "+this.getSalary()); } } class TestInheritance { public static void main(String[] args) { Person jenny = new Person("Jennifer"); Employee joey = new Employee("Joey", 200.0); Employee judy = new Employee("Judith", 550.0); System.out.println("*************************"); jenny.printDetails(); joey.printDetails(); judy.printDetails(); System.out.println("*************************"); } }