[C++] HackerRank : Inheritance Introduction

Aiya Aiyara
3 min readJan 5, 2024

--

Easy : C++ (Basic)

Photo by Markus Spiske on Unsplash

หนึ่งในลักษณะที่สำคัญของการเขียนโปรแกรมเชิงวัตถุคือ 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;
}

ผลลัพท์

--

--