แล้วก็มาถึงเรื่องสำคัญกันแล้วครับก็คือ Inheritance ซึ่งจัดเป็นการ reuse อย่างหนึ่งคือการนำ
class ที่มีอยู่แล้วมาเพิ่มเติมหรือเปลี่ยนแปลง function การทำงานจากของเดิมให้เหมาะกับงานของเรา
การ inheritance ใน java จะใช้ keyword extends มาดูตัวอย่างกันเลย
class Human {
public void talk() {
System.out.println("Human talk!");
}
}
class Man extends Human{
public void talk() {
System.out.println("Human talk!");
}
}
จากตัวอย่าง class Man ทำการ inherit จาก class Human แล้วทำการเปลี่ยนแปลงแก้ไข method
talk การเปลี่ยนแปลงนี้จะเรียกว่า "Overriding" ซึ่งทำได้โดยประกาศ Method ที่เหมือน super class ทุกอย่าง
เราสามารถสร้าง reference ของ Human มารับ instance ของ Man ได้เพราะว่า Man เป็น class ลูก
หรือ sub class ของ Human ส่วน Human จะเป็น super class ของ Man ซึ่ง reference
ของ Man จะไม่สามารถรับ instance ของ Human ได้ เช่น
class A {
public static void main(String[]args) {
Human h = new Man();//Correct!
Man m = new Human();//Compile Error!
}
}
เนื่องจาก class ทุกตัวจะถูก inherit มาจาก Object ดังนั้นเราสามารถสร้าง reference มา
รับ class ใดๆก็ได้เช่น
Object h = new Human();
Object m = new Man();
Object s = new String("Hello");
Object s2 = "hahaha";
===============
จากตัวอย่างข้างต้น เราสามารถประกาศ array ของ reference Human ได้ดังนี้
Human[]humans = {new Human(), new Man()};
for(Human h:humans)
h.talk();
ผลลัพท์จะขึ้นอยู่กับ instance ของ humans ที่ตำแหน่งบน array ที่ทำแบบนี้ได้เกิดการกลไกที่เรียกว่า
"Dynamic Binding" ซึ่งทำตอน runtime
นอกจากนี้เราสามารถที่จะเพิ่ม Data หรือ Method member
เข้าไปที่ class ลูกได้ เช่น
class Man extends Human{
public void talk() {
System.out.println("Human talk!");
}
public void walk() {
System.out.println("Human walk!");
}
}
Casting
จากตัวอย่างจะเห็น method walk ที่เพิ่มเข้ามาใน class Man หากเราใช้ reference ของ Human
ที่ถือ instance ของ Man แล้วต้องการเรียกใช้ method walk จะสามารถทำได้ดังนี้
Human h = new Man();
Man man = (Man)h;//Type Casting
man.walk();
โดยที่ Type Casting เป็นการแปลง reference ไปเป็น class ลูก ซึ่ง Compiler ไม่สามารถ
ตรวจสอบได้ว่า h ถือ instance Man จริงหรือไม่ จะตรวจสอบตอน runtime เท่านั้น
ลองดูตัวอย่างการ casting อีกตัวอย่างครับ
class Student extends Man {
public void learn() {
System.out.println("Student learn!");
}
}
Human h = new Student();
Man m = (Man)h;//Correct! เพราะ h ถือ instance ของ Student ซึ่งสืบทอดมาจาก Man
Student s = (Student)m;//Correct เพราะ m ถือ instance ของ Student
Man m2 = (Student)m;//Correct เพราะ reference ของ Super class สามารถ
ถือ instance ของ Sub class ได้
h = new Man();
Student s = (Student)h;//Error! เพราะ h ไม่ได้ถือ instance ของ Student
Shadowing
คือการประกาศตัวแปรชื่อเดียวกับที่ประกาศไว้แล้วใน super class เช่น
class A{
int i=999;
}
class B extends A {
boolean i=true;
void test() {
System.out.println(i);//อ้างอิงถึง i ของ B ซึ่งเป็น boolean
System.out.println(super.i);//อ้างอิงถึง i ใน super class
}
}
หากเรานำ reference A มารับ instance ของ class B แล้วอ้างถึง i จะเป็นการอ้างถึง int i ของ A
เพราะถูก "Static Binding" มาแล้วตั้งแต่ตอน Compile
A a = new B();
System.out.println(a.i);
จริงๆแล้วการทำ shadowing สามารถทำได้ในระดับ method เช่น
class A {
int i=999;
void test() {
System.out.println(i);//integer
boolean i=true;
System.out.println(i);//boolean
}
}
Overriding
เราสามารถ override method ของ super class ให้เปลี่ยนแปลงการทำงาน
แต่มีเงื่อนไขอยู่ว่า modifier ของ method ที่ต้องการ override ใน sub class
ต้องเท่ากับหรือสูงกว่า modifier ของ method ใน super class เช่น
class Human {
protected void talk() {
System.out.println("Human talk!");
}
}
class Man extends Human{
public void talk() {
System.out.println("Human talk!");
}
}
เราสามารถเรียงลำดับ modifier ได้ดังนี้คือ public > protected > default > private
class A {
protected void test(){}
}
class B {
void test(){}//Compile Error!
}
Final
เราสามารถใช้ keyword final หน้า class เพื่อป้องกันไม่ให้ใคร inherit class เราได้เช่น
final class A {}
class B extends A {}//Compile Error!
และสามารถวางไว้หน้า method เพื่อป้องกันการ override ได้เช่นกัน เช่น
class A {
final void test() {}
}
class B {
void test() {}//Compile Error
}
สอนพื้นฐาน Java
Line: wizarud
Gmail: [email protected]