การสืบทอดคุณสมบัติของคลาส
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("*************************");
}
}

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

  • 1.
  • 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("*************************"); } }