[C++] HackerRank : Inheritance Introduction
Easy : C++ (Basic)
หนึ่งในลักษณะที่สำคัญของการเขียนโปรแกรมเชิงวัตถุคือ Inheritance (การสืบทอด) ซึ่งเราจะมาทำความเข้าใจจากโจทย์ HackerRank ในข้อนี้กัน
ก่อนจะเริ่มเราต้องทำความเข้าใจถึงที่มาของมันว่าทำไมต้องมี มันไม่ได้มีเพื่อให้เขียนโปรแกรมยากขึ้น แต่มันมีขึ้นเพื่อให้เขียนได้ง่ายขึ้น … รึเปล่านะ ???
ผมจะยกตัวอย่าง Painpoint (ปัญหา) ของ Code ชุดหนึ่ง เริ่มจากผมจะสร้าง Class ขึ้นมาหนึ่ง Class ชื่อว่า CarBrand โดยผมสร้าง 2 Methods แสดงชื่อยี่ห้อ Toyota กับ Benz
class ฺCarBrand {
public:
void JapaneseBrand(){
cout << "Toyota : ";
}
void EuropeBrand(){
cout << "Benz : ";
}
};
ให้ Main เรียกใช้ Method ที่อยู่ใน Class Brand แบบนี้
จินตนาการว่าผมเป็น Dealer รถสองยี่ห้องนี้ มีสิทธิ์ขายรถสองยี่ห้อนี้แต่เพียงผู้เดียวในประเทศไทย โดยในไตรมาสแรก ผมอยากจะกำหนดให้แต่ละยี่ห้อขายได้แค่นี่ห้อละ 3 จังหวัด
Toyota : Bangkok
Toyota : Nonthaburi
Toyota : Pathumthani
Benz : ChiangMai
Benz : Lumpang
Benz : Nan
ผมจะสร้าง Class เพิ่มขึ้นมาอีก Class เป็น Class CountryZone มี 2 เช่นกัน
class CountryZone {
public:
void CentralZone(){
cout << "Bangkok\n";
cout << "Nonthaburi\n";
cout << "Pathumthani\n";
}
void NorthZone(){
cout << "ChiangMai\n";
cout << "Lumpang\n";
cout << "Nan\n";
}
};
ผมจะให้ Class CountryZone สืบทอด Class Brand มาใช้งานแบบนี้
class CountryZone : public ฺCarBrand {
// รูปแบบการสืบทอด
public:
void CentralZone(){
JapaneseBrand(); cout << "Bangkok\n";
JapaneseBrand(); cout << "Nonthaburi\n";
JapaneseBrand(); cout << "Pathumthani\n";
}
void NorthZone(){
EuropeBrand(); cout << "ChiangMai\n";
EuropeBrand(); cout << "Lumpang\n";
EuropeBrand(); cout << "Nan\n";
}
};
เท่ากับว่าตอนนี้ใน Class CountryZone ได้สืบทอด Method ชื่อ Brand มาใช้ได้ ใน Main ไม่ต้องเปลี่ยนอะไรเลย
ผมจะเพิ่มข้อมูลอีกนิดคือต้องแสดงราคาของแต่ละภูมิภาคด้วยการสร้าง Class Price เพิ่มขึ้นมาอีก
class Price : public CountryZone {
public:
void EvenPrice(){
CentralZone();
cout << "200,000\n";
}
void OddPrice(){
NorthZone();
cout << "300,000\n";
}
};
จากนั้นก็ให้ Main เรียกรถทุกยี่ห้อที่มีราคา 200,000 กับ 300,000 ขึ้นมาดู
ผมเปลี่ยนใจแล้ว ผมอยากเรียกดูเฉพาะยี่ห้อ (แต่ต้องใช้ Instance เดิม)
int main() {
Price carInstance;
carInstance.JapaneseBrand();
cout << endl;
return 0;
}
ผลลัพท์
เท่ากับว่า Class Price ของผมจะมีทุกอย่างที่ Class Country และ CarBrand มี
จะเห็นว่าการสืบทอดทำให้อ่าน Code ได้ง่ายขึ้น จัดวาง Catagory ของข้อมูลได้ดี เรียกใช้ได้ง่ายและที่สำคัญมันลดความซ้ำซ้อน
มาดูโจทย์ของเรากันดีกว่า โจทย์ต้องการให้ 2 Classes นี้
class Triangle{
public:
void triangle(){
cout<<"I am a triangle\n";
}
};
class Isosceles : public Triangle{
public:
void isosceles(){
cout<<"I am an isosceles triangle\n";
}
};
มีการสืบทอดกันโดยใน Main จะเรียกใช้ Function ในแต่ละ Class แบบนี้
int main(){
Isosceles isc;
isc.isosceles();
isc.triangle();
return 0;
}
ถ้าเรา Compile เลยจะได้ Output แบบนี้
I am an isosceles triangle
I am a triangle
แต่โจทย์จะให้เราเขียน Function ใน Class Isosceles เพื่อให้ได้ผลแบบนี้
I am an isosceles triangle
In an isosceles triangle two sides are equal
I am a triangle
เราจึงต้องเพิ่ม Code ใน Function Isosceles อีกหนึ่งบรรทัด
class Isosceles : public Triangle{
public:
void isosceles(){
cout<<"I am an isosceles triangle\n";
cout<<"In an isosceles triangle two sides are equal\n";
}
};
แต่ง Code แล้วเอาไป Run
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
class Triangle{
public:
void triangle(){
cout<<"I am a triangle\n";
}
};
class Isosceles : public Triangle{
public:
void isosceles(){
cout<<"I am an isosceles triangle\n";
cout<<"In an isosceles triangle two sides are equal\n";
}
};
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
Isosceles isc;
isc.isosceles();
isc.triangle();
return 0;
}
ผลลัพท์
Source Code : https://github.com/MarkTBSS/22_Inheritance_Introduction