Inheritances ในภาษา JavaScript
ในบทนี้ คุณจะได้เรียนรู้การสืบทอดคลาสในภาษา JavaScript การสืบทอดคลาสนั้นเป็นคุณสมบัติอย่างหนึ่งในการเขียนโปรแกรมเชิงวัตถุ (OOP) ที่ทำให้เราสามารถสร้างคลาสใหม่โดยเพิ่มเติม (Extend) ความสามารถจากคลาสเดิมที่มีอยู่ได้ซึ่งเป็นแนวคิดของการนำโค้ดกลับมาใช้ใหม่ (Reuse) นี่เป็นเนื้อหาในบทนี้
- การสืบทอดคลาส
- การใช้คำสั่ง super
- การ Override เมธอด
- การสืบทอดคลาสแบบหลายขั้น
- คลาส Object
การสืบทอดคลาส
การสืบทอดคลาส (Inheritances) คือคุณสมบัติของคลาสในภาษา JavaScript ที่ให้เราสามารถสร้างคลาสใหม่โดยการสืบทอด Property และเมธอดจากคลาสเดิมที่มีอยู่แล้วได้ นี่เป็นคุณสมบัติที่มีประโยชน์มากในการเขียนโปรแกรมเชิงวัตถุสำหรับการนำโค้ดเดิมกลับมาใช้ใหม่ เนื่องจากเราไม่ต้องเขียนโค้ดขึ้นมาใหม่ทั้งหมด แต่เพียงแค่สืบทอดคุณสมบัติจากคลาสเดิมที่มีอยู่แล้ว
นี่เป็นรูปแบบของการสืบทอดคลาสในภาษา JavaScript
class DeriveredClass extends BaseClass {
// Class definitions
}
เมื่อ BaseClass
นั้นเป็นคลาสหลักที่ต้องการสืบทอดไปยังคลาสย่อย DeriveredClass
การสืบทอดนั้นจะใช้คำสั่ง extends
หลังจากการประกาศคลาสย่อยตามด้วยชื่อของคลาสหลักที่ต้องการสืบทอด นี่จะทำให้ Property และเมธอดที่ถูกกำหนดในคลาส BaseClass
ถูกสืบทอดมากยังคลาส DeriveredClass
นี่เป็นตัวอย่างของโปรแกรมสำหรับการสืบทอดคลาสในภาษา JavaScript เราจะสร้างคลาสของบุคคลที่ประกอบไปด้วยคุณสมบัติพื้นฐานที่ทั้งคลาสโปรแกรมเมอร์และคลาสนักกีฬาสามารถสืบทอดไปใช้งานได้ นี่เป็นตัวอย่าง
class Person {
constructor(fistName, lastName) {
this.fistName = fistName;
this.lastName = lastName;
}
getFullName() {
return this.fistName + " " + this.lastName;
}
}
class Programmer extends Person {
setLanguage(lang) {
this.language = lang;
}
introduce() {
let str = this.getFullName();
str += " is a " + this.language;
str += " programmer";
console.log(str);
}
}
class Athlete extends Person {
setSport(sport) {
this.sport = sport;
}
playSport() {
let str = this.getFullName();
str += " plays " + this.sport;
console.log(str);
}
}
let p = new Programmer("Matteo", "Marcus");
p.setLanguage("JavaScript");
a.introduce();
a.getFullName();
let a = new Athlete("Lionel", "Messi");
a.setSport("Football");
a.playSport();
a.getFullName();
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
Matteo Marcus is a JavaScript programmer
Matteo Marcus
Lionel Messi plays Football
Lionel Messi
ในตัวอย่างเราได้สร้างคลาส Person
คลาสนี้ประกอบไปด้วยสอง Property คือ fistName
และ lastName
สำหรับเก็บชื่อและนามสกุลตามลำดับ และเมธอด getFullName
รับเอาชื่อแบบเต็ม เราจะใช้คลาสนี้เป็นคลาสหลักที่จะสืบทอดโดยคลาสอื่นๆ ที่ต้องการคุณสมบัติเหล่านี้
class Programmer extends Person {
...
}
class Athlete extends Person {
...
}
จากนั้นเราประกาศคลาส Programmer
ซึ่งเป็นคลาสของโปรแกรมเมอร์ และคลาส Athlete
ซึ่งเป็นคลาสของนักกีฬาโดยสืบทอดมาจากคลาส Person
เนื่องจากทั้งโปรแกรมเมอร์และนักกีฬาต้องมีชื่อและนามสกุลอยู่แล้ว ดังนั้นมันสามารถสืบทอดจากคลาส Person
เพื่อใช้ข้อมูลเหล่านี้โดยไม่ต้องเขียนขึ้นมาใหม่
สิ่งที่ทั้งสองคลาสต้องเพิ่มเข้ามาก็คือ คลาสโปรแกรมเมอร์จะมีการเก็บภาษาเขียนโปรแกรม และคลาสของนักกีฬาจะมีการเก็บชื่อของกีฬาที่เล่น นี่จะแสดงให้เห็นว่าคลาส Person
เป็นคลาสที่มีคุณสมบัติทั่วไปแบบกว้างๆ ส่วนคลาส Programmer
และ Athlete
นั้นเป็นที่เฉพาะเจาะจงมากขึ้น
let p = new Programmer("Matteo", "Marcus");
p.setLanguage("JavaScript");
a.introduce();
a.getFullName();
let a = new Athlete("Lionel", "Messi");
a.setSport("Football");
a.playSport();
a.getFullName();
จากนั้นเป็นการนำคลาสมาสร้างออบเจ็ค และอย่างที่คุณเห็น คลาสทั้งสองสามารถเรียกใช้เมธอด getFullName
ที่ถูกประกาศในคลาส Person
ซึ่งเป็นคลาสที่มันสืบทอดมาจาก เหมือนกับว่าเมธอดนี้ถูกประกาศไว้ในคลาสของมันเองได้ และนอกจากนี้แต่ละคลาสยังมีการเรียกเมธอดของมันเองที่ถูกประกาศไว้ในแต่ละคลาส
นี่แสดงให้เห็นว่าเราสามารถนำคลาสเดิมที่มีอยู่แล้วกลับมาใช้ใหม่โดยการสืบทอดและเพิ่มเติมความสามารถเข้าไป ซึ่งนี่มีประโยชน์มากในการเขียนโปรแกรม เมื่อหลายคลาสต้องการแชร์คุณสมบัติบางอย่างร่วมกัน เราสามารถนำคุณสมบัติเหล่านั้นกำหนดในคลาสหลักได้และใช้การสืบทอดมาแทน
และข้อดีอีกอย่างหนึ่งของการสืบทอดคือเมื่อมีการเปลี่ยนแปลงในคลาสหลัก จะส่งผลไปยังคลาสที่ได้รับการสืบทอดทุกคลาส ยกตัวอย่างเช่น ถ้าหากเราเพิ่มเมธอดใหม่ในคลาส Person
ทั้งคลาส Programmer
และ Athlete
จะได้รับการเปลี่ยนแปลงนั้นด้วย
การใช้คำสั่ง super
คำสั่ง super เป็นคำสั่งที่่ใช้สำหรับอ้างถึงคอนสตรัคเตอร์หรือเมธอดของคลาสหลัก เมื่อเราไม่ได้สร้างคอนสตรัคเตอร์ในคลาสย่อย ภาษา JavaScript จะสร้างคอนสตรัคเตอร์ว่างเปล่าให้อัติโนมัติในตอนที่โปรแกรมทำงาน แต่เมื่อไรก็ตามที่คลาสย่อยมีการประกาศคอนสตรัคเตอร์ เราจะต้องเรียกใช้งานคอนสตรัคเตอร์ของคลาสหลักเสมอด้วยเมธอด super()
โดยทั่วไปแล้วคลาสย่อยมักจะกำหนดคอนสตรัคเตอร์เพื่อทำงานบางอย่างที่แตกต่างไปจากคลาสหลัก นั่นเป็นเรื่องปกติเนื่องจากเราสืบทอดคลาสเพื่อใช้โค้ดเดิมที่มีอยู่และเพิ่มความสามารถให้กับมัน
ในตัวอย่างนี้ จะเป็นการกำหนดคอนสตรัคเตอร์ในคลาสย่อย อย่างที่คุณรู้ว่ารูปสี่เหลี่ยมและลูกบาศก์นั้นมีคุณสมบัติบางอย่างที่เหมือนกัน เช่น ความยาวและความสูง เราจะใช้มันสำหรับแสดงตัวอย่างการใช้งานคำสั่ง super
ในภาษา JavaScript
class Rectangle {
constructor(width, height) {
this.width = width;
this.height = height;
}
area() {
return this.width * this.height;
}
}
class Cube extends Rectangle {
constructor(width, height, dept) {
super(width, height);
this.dept = dept;
}
volume() {
return this.area() * this.dept;
}
}
let rect = new Rectangle(3, 4);
console.log("Area of rectangle:", rect.area());
let cube = new Cube(1, 2, 3);
console.log("Volume of cube:", cube.volume());
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
Area of rectangle: 12
Volume of cube: 6
คลาส Rectangle
นั้นเป็นคลาสสำหรับรูปสี่เหลี่ยมที่ประกอบไปด้วยสอง Property คือความยาว width
และความสูง height
เราสามารถใช้คลาสนี้สำหรับสร้างออบเจ็คของรูปสี่เหลี่ยมที่มีขนาดใดๆ ได้ แต่นั่นไม่ใช้สิ่งที่เราต้องการทำในตอนนี้
class Cube extends Rectangle {
constructor(width, height, dept) {
super(width, height);
this.dept = dept;
}
...
เราสร้างคลาส Cube
ที่สืบทอดมาจากคลาส Rectangle
คลาสนี้เป็นคลาสสำหรับลูกบาศก์ที่ประกอบไปด้วยความยาว width
ความสูง height
หรือเป็นการเพิ่มมิติที่สามจากรูปสี่เหลี่มเข้ามานั่นคือความลึก dept
เนื่องจากคลาสนี้มี Property บางอย่างที่เหมือนกับคลาส Rectangle
ดังนั้นการสืบทอดจากคลาสที่มันอยู่แล้วแทน
แม้ว่าคลาส Cube
จะได้รับการสืบทอด Property ทั้งหมดจากคลาส Rectangle
แล้ว แต่มันยังคงมี Property เพิ่มเข้าสำหรับความลึกเข้ามา ดังนั้นมันจำเป็นจะต้องมีคอนสตรัคเตอร์เป็นของมันเองสำหรับรับค่าความลึกในตอนที่สร้างออบเจ็ค
constructor(width, height, dept) {
super(width, height); // Must call first
this.dept = dept;
}
คลาส Cube
จะต้องสร้างคอนสตรัคเตอร์เป็นของมันเองเนื่องจากมันในการสร้างกล่องนั่นต้องการสามพารามิเตอร์ แต่คอนสตรัคเตอร์ในคลาส Rectangle
มีเพียงแค่สอง
แต่เนื่องจากว่า width
และ height
นั้นเป็น Property ที่สืบทอดมาจากคลาสหลัก Rectangle
เราสามารถเรียกใช้คอนสตรัคเตอร์ของคลาสหลักเพื่อกำหนดค่าเหล่านี้ได้ด้วยคำสั่ง super(width, height)
สิ่งที่เราต้องทำเพิ่มในคอนสตรัคเตอร์ของคลาส Cube
คือกำหนด Property dept
สำหรับความลึกที่เพิ่มเข้ามานั่นเอง
หรือเราสามารถกำหนด Property ใหม่ทั้งหมดในคอนสตรัคเตอร์ของคลาส Cube
ได้ ซึ่งให้ผลลัพธ์การทำงานที่เหมือนกัน แต่อย่างี่บอกแล้วว่าเนื่องจากคอนสตรัคเตอร์ของคลาสหลักทำหน้าที่นี้อยู่แล้ว เราควรใช้มันแทนที่จะเขียนขึ้นใหม่
constructor(width, height, dept) {
super(); // Must call first
this.width = width;
this.height = height;
this.dept = dept;
}
แต่สิ่งหนึ่งที่เป็นข้อบังคับในภาษา JavaScript ก็คือเมื่อคลาสย่อยมีคอนสตรัคเตอร์เป็นของมันเอง เราจะต้องเรียกใช้คอนสตรัคเตอร์ของคลาสหลักก่อนเสมอ ไม่เช่นนั้นเราจะไม่สามารถใช้คำสั่ง this
สำหรับกำหนดค่า Property ในคลาสนี้ได้
การ Override เมธอดและคำสั่ง super
การ Override เมธอดคือการกำหนดการทำงานใหม่ให้กับเมธอดในคลาสย่อยโดยที่เมธอดยังมีชื่อเหมือนเดิมแต่การทำงานเปลี่ยนไป เมื่อทำการ Override เมธอด การเรียกใช้งานเมธอดจากออบเจ็คของคลาสย่อยจะเป็นการทำงานใหม่ของเมธอดในคลาสใหม่แทน มาดูตัวอย่างการ Override เมธอดในภาษา JavaScript
class Animal {
move() {
console.log("Animal is moving");
}
}
class Dog extends Animal {
move() {
console.log("Dog is running");
}
thisMove() {
this.move();
}
baseMove() {
super.move();
}
}
let dog = new Dog();
dog.move();
dog.thisMove();
dog.baseMove();
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
Dog is running
Dog is running
Animal is moving
ในตัวอย่างนี้ เราได้สร้างคลาส Animal
ซึ่งเป็นคลาสของสัตว์ที่มีหนึ่งเมธอด move
สำหรับการเคลื่อนที่ของสัตว์ จากนั้นเราสร้างคลาส Dog
โดยสืบทอดมาจากคลาส Animal
move() {
console.log("Dog is running");
}
คลาส Dog
นั้นเป็นคลาสที่สืบทอดมาจากคลาส Animal
แต่ในบางครั้งเราอาจต้องการกำหนดการทำงานเมธอด move
ของคลาสนี้ใหม่ที่แตกต่างไปจากคลาสหลักของมัน แต่ยังคงต้องการใช้ชื่อเมธอดเดิม เราสามารถทำเช่นนั้นได้โดยการสร้างเมธอดในคลาส Dog
อีกครั้งและกำหนดการทำงานใหม่สำหรับคลาสนี้ ซึ่งนี่เรียกว่าการ Override เมธอด
let dog = new Dog();
dog.move();
dog.thisMove();
นั่นจะทำให้ตอนนี้เมื่อเราเรียกใช้เมธอด this.move
ภายในคลาสหรือจากออบเจ็ค dog.move
จะเป็นการทำงานใหม่ของเมธอดจากคลาส Dog
แทน ในกรณีนี้ ทำให้เราสามารถเปลี่ยนแปลงการทำงานของเมธอดไปตามหน้าที่ของแต่ละคลาสได้
baseMove() {
super.move();
}
อย่างไรก็ตาม เรายังสามารถเข้าถึงเมธอดของคลาสหลักได้ด้วยคำสั่ง super
ตามด้วยชื่อของเมธอดได้ แต่การเข้าถึงนี้จะต้องทำภายในคลาส Dog
เท่านั้น เราจะไม่สามารถเข้าถึงเมธอดของคลาสหลักได้จากคำสั่ง this.move
หรือ dog.move
ซึ่งเป็นออบเจ็คของคลาส Dog
ได้เนื่องจากว่ามันถูก Override ไปแล้วนั่นเอง
นี่จะทำให้แม้ว่าเมธอดจะถูก Override ไปแล้วแต่คลาสย่อยยังสามารถเข้าถึงการทำงานพื้นฐานจากคลาสหลักได้ในกรณีที่ต้องการใช้มัน ซึ่งจะแสดงให้คุณเห็นในตัวอย่างต่อไป
ในตัวอย่างนี้จะเป็นการ Override เมธอด draw
เพื่อให้คลาสย่อยสามารถทำงานตามบริษทของแต่ละคลาสได้ และยังคงสามารถเรียกใช้เมธอดของคลาสหลัก ในขณะที่ชื่อของเมธอดนั้นยังคงเหมือนเดิมไม่เปลี่ยนแปลง
class Polygon {
constructor(width, height) {
this.width = width;
this.height = height;
}
draw(data) {
console.log("Perform actual draw from base class");
console.log(data);
}
}
class Rectangle extends Polygon {
draw(ch) {
let buffer = [];
for (let i = 0; i < this.height; i++) {
buffer.push(ch.repeat(this.width));
}
super.draw(buffer.join("\n"));
}
}
let rect = new Rectangle(4, 3);
rect.draw("#");
rect.draw("M");
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
Perform actual draw from base class
####
####
####
Perform actual draw from base class
MMMM
MMMM
MMMM
ในตัวอย่างนี้ เราได้สร้างคลาส Rectangle
ที่สืบทอดมาจากคลาส Polygon
เนื่องจากว่าในเมธอด draw
ของคลาสหลักนั้นทำหน้าที่แค่วาดข้อความออกทางหน้าจอเท่านั้น ดังนั้นในคลาส Rectangle
จะสามารถกำหนดรูปแบบการวาดเป็นของมันเอง และเรียกใช้เมธอดของคลาสหลักสำหรับการวาดจริงๆ
ซึ่งนี่จะทำให้ชัดเจนเมื่อเรามีอีกคลาสที่สืบทอดจากคลาส Polygon
เช่นเดียวกัน แต่มันต้องการทำงานสำหรับการวาดที่แตกต่างกันออกไป ยกตัวอย่างเช่น
class Polygon {
...
}
class Triangle extends Polygon {
draw(ch) {
let buffer = [];
for (let i = 0; i < this.height; i++) {
buffer.push(
ch.repeat((i + 1) / this.height * this.width)
);
}
super.draw(buffer.join("\n"));
}
}
let tri = new Triangle(5, 5);
tri.draw("#");
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
Perform actual draw from base class
#
##
###
####
#####
Perform actual draw from base class
M
MM
MMM
MMMM
MMMMM
คลาส Triangle
นั้นต้องการสืบทอดจากคลาส Polygon
เช่นเดียวกัน เนื่องจากวิธีการวาดรูปสามเหลี่ยมนั้นจะแตกต่างจากรูปสี่เหลี่ยม นั่นทำให้คลาสนี้ทำการ Override เมธอด draw
เพื่อให้สอดคล้องกับการทำงานของมันเอง แต่มันยังคงสามารถเรียกใช้งานเมธอด draw
จากคลาสหลักสำหรับการวาดจริงๆ ได้
กล่าวคือเมธอด draw
ในคลาส Polygon
นั้นเป็นเมธอดหลักสำหรับการวาดที่คลาสย่อยสามารถเรียกใช้งานได้ เมื่อการทำงานในเมธอด draw
ของแต่ละคลาสเสร็จสิ้น และในตอนท้ายเมธอด draw
ของทั้งคลาส Rectangle
และ Triangle
เรียกใช้เมธอด super.draw
ของคลาสหลัก
super.draw(buffer.join("\n"));
นี่เพื่อแสดงให้คุณเห็นว่าคลาสย่อยแต่ละคลาสสามารถ Override เมธอดเพื่อเพิ่มความสามารถที่มีเข้ามาได้ในขณะที่ยังสามารถใช้โค้ดบางอย่างร่วมกันจากคลาสหลักของมัน ถึงแม้ว่าในความเป็นจริงแล้ว เราสามารถเขียนโค้ดจากเมธอด draw
ไว้ในคลาสย่อยทั้งสองได้ เช่นนำโค้ดสองบรรทัดนี้เขียนแยกในเมธอด draw
ของคลาสย่อยแต่ละคลาส
console.log("Perform actual draw from base class");
console.log(data);
แต่การทำเช่นนี้จะเป็นการเขียนโค้ดซ้ำ ลองจินตนาการว่าในเมธอด draw
ของคลาสหลักมีโค้ดที่การทำงานเป็นจำนวนมาก การนำมันมาเขียนใหม่ทั้งหมดคงจะไม่ใช้วิธีที่ดีและไม่ได้เป็นการใช้งานสามารถของการสืบทอด
การสืบทอดคลาสแบบหลายขั้น
คลาสในภาษา JavaScript นั้นสามารถสืบทอดมากกว่าหนึ่งลำดับชั้นได้ ยกตัวอย่างเช่น คลาส B
สืบทอดมาจากคลาส A
จากนั้นเราสามารถสร้างคลาส C
เพื่อสืบทอดจากคลาส B
ได้ นั่นจะทำให้คลาส C
มีความสามารถเหมือนกับที่คลาส A
และคลาส B
มี เราเรียกการสืบทอดในรูปแบบนี้ว่าการสืบทอดแบบลำดับชั้น
ในตัวอย่างถัดไป เราจะมาแสดงวิธีการสืบทอดคลาสในรูปแบบดังกล่าว โดยการแสดงการทำงานของคลาสลูกบอล ซึ่งสามารถสืบทอดมาจากคลาสของทรงกลมและวงกลม นี่เป็นตัวอย่าง
class Circle {
constructor(r) {
this.radius = r;
}
getDiameter() {
return this.radius * 2;
}
getArea() {
return Math.PI * (this.radius ** 2);
}
}
class Sphere extends Circle {
constructor(r) {
super(r);
}
getVolume() {
return 4 / 3 * Math.PI * (this.radius ** 3);
}
}
class Ball extends Sphere {
constructor(r, color, price) {
super(r);
this.color = color;
this.price = price;
}
}
let balls = [
new Ball(3.5, "Red", 8.90),
new Ball(4.33, "Blue", 15.00)
];
for (let ball of balls) {
console.log("Product name: %s Ball", ball.color);
console.log("Color: %s", ball.color);
console.log("Price: %s USD", ball.price);
console.log("Diameter: %s Inches", ball.getDiameter());
console.log("Wind volume: %s Cubic inches",
ball.getVolume().toFixed(2));
}
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
Product name: Red Ball
Color: Red
Price: 8.9 USD
Diameter: 7 Inches
Wind volume: 179.59 Cubic inches
Product name: Blue Ball
Color: Blue
Price: 15 USD
Diameter: 8.66 Inches
Wind volume: 340.06 Cubic inches
ในตัวอย่างนี้ เป็นการแสดงการสืบทอดคลาสแบบหลายชั้นในภาษา JavaScript เราได้ประกาศสามคลาสซึ่งมีการสืบทอดแบบต่อเนื่องกัน คลาส Circle
เป็นคลาสของวงกลมที่มีหนึ่ง Property radius
ซึ่งเป็นรัศมีของวงกลม และมีสองเมธอดคือ getDiameter
และ getArea
สำหรับหาเส้นผ่านศูนย์กลางและพื้นที่ของวงกลมตามลำดับ
class Sphere extends Circle {
constructor(r) {
super(r);
}
getVolume() {
return 4 / 3 * Math.PI * (this.radius ** 3);
}
}
จากนั้นเราสร้างคลาส Sphere
ซึ่งเป็นคลาสของทรงกลมที่สืบทอดมาจากคลาส Circle
คลาสนี้มี Property radius
เหมือนกับที่วงกลมมี แต่สิ่งที่เพิ่มเข้ามาคือเมธอด getVolume
สำหรับค่าปริมาตรของทรงกลมจากรัศมีของมัน และอย่างที่เรารู้ว่าทรงกลมคือก็วงกลมในสามมิตินั่นเอง
class Ball extends Sphere {
constructor(r, color, price) {
super(r);
this.color = color;
this.price = price;
}
}
และสุดท้ายเราสร้างคลาส Ball
ที่สืบทอดมาจากคลาส Sphere
เนื่องจากลูกบอลนั้นมีรัศมีและเป็นทรงกลม และคลาส Sphere
มีสิ่งเหล่านี้อยู่แล้ว การสืบทอดทำให้เราไม่ต้องกำหนดคุณสมบัติและเมธอดทั้งหมดที่ลูกบอลควรมีใหม่ ทั้งหมดที่เราทำในคลาสของลูกบอลคือกำหนด Property เพิ่มเติมที่ลูกบอลควรมีนั่นก็คือ สีและราคาของลูกบอล
let balls = [
new Ball(3.5, "Red", 8.90),
new Ball(4.33, "Blue", 15.00)
];
for (let ball of balls) {
console.log("Product name: %s Ball", ball.color);
console.log("Color: %s", ball.color);
console.log("Price: %s USD", ball.price);
console.log("Diameter: %s Inches", ball.getDiameter());
console.log("Wind volume: %s Cubic inches",
ball.getVolume().toFixed(2));
}
จากนั้นเราสร้างออบเจ็คของลูกบอลจากคลาส Ball
เก็บไว้ในอาเรย์และใช้คำสั่ง for loop เพื่อวนออบเจ็คเพื่อแสดงรายละเอียดของลูกบอลออกทางหน้าจอ นี่เป็นการแสดงรายละเอียดของสินค้าลูกบอลเหมือนกันในเว็บไซต์ขายของออนไลน์ที่คุณเคยเจอ
นอกจากนี้ เราสามารถสร้างคลาสอื่นที่มีคุณสมบัติเป็นทรงกลมเพื่อสืบทอดจากคลาส Sphere
ได้ ในตัวอย่างนี้เราได้สร้างคลาส Star ซึ่งเป็นคลาสของดวงดาว นี่เป็นตัวอย่าง
class Circle {
...
}
class Sphere extends Circle {
...
}
class Star extends Sphere {
constructor(name, r) {
super(r);
this.name = name;
}
getSurfaceArea() {
return 4 * Math.PI * (this.radius ** 2);
}
}
let s1 = new Star("Earth", 6371);
let s2 = new Star("Moon", 1737.1);
let s3 = new Star("Sun", 696340);
console.log("We live on the blue planet called %s", s1.name);
console.log("Radius: %f km", s1.radius);
console.log("Surface area: %d sq km", s1.getSurfaceArea());
console.log("%s has one planet called the %s", s1.name, s2.name);
console.log("Radius: %f km", s2.radius);
console.log("Surface area: %d sq km", s2.getSurfaceArea());
console.log("%s is orbiting around the %s", s1.name, s3.name);
console.log("The %s has a diameter of %d km",
s3.name, s3.getDiameter());
กำหนดให้คลาส Circle
และคลาส Sphere
ได้ถูกประกาศเหมือนกับในตัวอย่างก่อนหน้า ดังนั้นในตัวอย่างนี้เราสร้างคลาส Star
ที่สืบทอดมาจากคลาส Sphere
โดยคลาสนั้นมี Property เพิ่มเติมคือชื่อของดวงดาว และเมธอดสำหรับหาพื้นที่ผิวของดวงดาว
ในความเป็นจริงแล้วดวงดาวไม่ได้เป็นทรงกลมที่สมบูรณ์แบบ ดังนั้นเมธอดหาพื้นที่ผิวนั้นเป็นค่าโดยประมาณเท่านั้น จากนั้นเราสร้างสามออบเจ็คจากคลาส Star
ซึ่งเป็นออบเจ็คของโลก ดวงจันทร์ และดวงอาทิตย์ และแสดงรายละเอียดเกี่ยวกับออบเจ็คออกทางหน้าจอ
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
We live on the blue planet called Earth
Radius: 6371 km
Surface area: 510064471.90978825 sq km
Earth has one planet called the Moon
Radius: 1737.1 km
Surface area: 37919229.54297058 sq km
Earth is orbiting around the Sun
The Sun has a diameter of 1392680 km
คลาส Object
จะเห็นว่าคลาสสามารถสืบทอดแบบเป็นลำดับชั้นมายังคลาสที่เฉพาะเจาะจงมากขึ้นได้ ซึ่งนี่เป็นแนวคิดของคลาสและออบเจ็คในภาษา JavaScript โดยทุกคลาสในภาษา JavaScript นั้นสืบทอดมาจากคลาสสูงสุดที่เรียกว่า Object
ยกตัวอย่างเช่น
class Being {
// empty class
}
let a = new Being();
console.log(a.toString());
console.log(a instanceof Object);
นี่เป็นผลลัพธ์การทำงานของโปรแกรม
[object Object]
true
นี่เป็นการพิสูจน์ให้เห็นว่าคลาสทุกคลาสในภาษา JavaScript นั้นสืบทอดมาจากคลาส Object
ซึ่งนี่เกิดขึ้นอัตโนมัติเมื่อเราสร้างคลาสและไม่ได้ระบุคลาสสำหรับการสืบทอด นั่นเป็นเหตุผลว่าทำไมเราสามารถเรียกใช้งานเมธอด toString
บนออบเจ็คของคลาส Being
เนื่องจากมันถูกกำหนดในคลาสหลัก Object
นั่นเอง
console.log(a instanceof Object);
ตัวดำเนินการ instanceof
ใช้สำหรับตรวจสอบว่าออบเจ็คถูกสร้างมาจากคลาสดังกล่าวหรือไม่ ตัวดำเนินการตรวจสอบว่าออบเจ็ค a
เป็นออบเจ็คของคลาส Being
และคลาสหลักของมันทั้งหมด และส่งค่ากลับเป็นจริงถ้าหากใช่
ในบทนี้ คุณได้เรียนรู้เกี่ยวกับการสืบทอดคลาสในภาษา JavaScript ซึ่งเป็นคุณสมบัติที่ทรงพลังในการเขียนโปรแกรมเชิงวัตถุ เนื่องจากมันช่วยให้เราสามารถใช้คลาสเดิมที่มีอยู่แล้ว เพื่อนำมาเพิ่มเติมความสามารถเข้าไปได้