Invoking an overloaded constructure using this keyword
ศศิพร โพธิ์ชะคุ้ม 650710582
การใช้คีย์เวิร์ด this เรียก constructor ที่ถูก overloaded ช่วยให้การจัดการและสร้างอ็อบเจ็กต์ภายในคลาสเดียวกันมีความยืดหยุ่นและมีประสิทธิภาพมากขึ้นทั้งลดความซับซ้อนในการทำซ้ำโค้ด ทำให้เข้าใจได้ง่ายยิ่งขึ้น
ข้อสำคัญของการใช้ this
คอนสตรัคเตอร์ที่ถูกเรียกด้วย this ต้องอยู่ใน class เดียวกันเสมอ
สามารถส่งพารามิเตอร์ให้กับคอนสตรัคเตอร์ที่ถูกเรียกได้
ชี้ไปที่สมาชิกของคลาสที่ถูกใช้งานอยู่เสมอ หรือก็คืออินสแตนซ์ของคลาสที่เราใช้งานในขณะนั้น
เป็นตัวบอก compiler ให้เรียกใช้ คอนสตรัคเตอร์เริ่มต้น(default constructor) หรือ constructor คอนสตรัคเตอร์ที่ไม่มีอาร์กิวเมนต์
การเรียกคอนสตรัคเตอร์ด้วย this
คอนสตรัคเตอร์สามารถเรียกใช้อีกคอนสตรัคเตอร์หนึ่งในออบเจ็กต์เดียวกันได้ โดยใช้คำสั่ง
this
ซึ่งสามารถใช้งานได้ทั้งคอนสตรัคเตอร์มีพารามิเตอร์และไม่มีพารามิเตอร์(default constructor)พารามิเตอร์ในคอนสตรัคเตอร์จะสามารถใช้เป็นพารามิเตอร์สำหรับ
this
หรือใช้ในนิพจน์ (expression) ก็ได้
Syntax
class X
{
public X: this()
{
// โค้ด..
}
}
ตัวอย่างโปรแกรม
ตัวอย่างที่ 1
// C# program to illustrate how to invoke
// overloaded constructor using this keyword
using System;
class Geek {
// Constructor without parameter(default constructor)
public Geek()
{
Console.WriteLine("Hello! Constructor 1");
}
// Constructor with parameter
// Here this keyword is used
// to call Geek constructor
public Geek(int a)
: this()
{
Console.WriteLine("Hello! Constructor 2");
}
}
// Driver Class
public class GFG {
// Main method
static public void Main()
{
// Create object of Geek class
Geek obj = new Geek(2);
}
}
ในตัวอย่างนี้ จะเห็นได้ว่าคลาส Geek มีคอนสตรัคเตอร์ อยู่ 2 ตัว คือ
Geek() ไม่มีพารามิเตอร์ โดยคอนสตรัคเตอร์นี้จะถูกเรียกเมื่อสร้างอ็อบเจ็กต์
Geek
โดยไม่มีการส่งพารามิเตอร์เข้าไปGeek(int a) มีพารามิเตอร์ 1 ตัว คือ
int a
โดยคอนสตรัคเตอร์นี้มีการเรียกใช้this()
เพื่อเรียกคอนสตรัคเตอร์ที่ไม่มีพารามิเตอร์ก่อนที่จะทำงานในบล็อกนี้ ซึ่งจะทำให้ข้อความ "Hello! Constructor 1" ถูกพิมพ์ออกมาก่อน
ในคลาส CFG ซึ่งทำหน้าที่เป็น main ของโปรแกรม จะเห็นได้ว่า
เป็นการสร้างอ็อบเจ็กต์ที่เรียกคอนสตรัคเตอร์ที่มีพารามิเตอร์ นั่นคือ Geek(int a) จะถูกเรียกใช้ ซึ่งการที่จะมีการทำงานในส่วนของคอนสตรัคเตอร์นี้ จะมีการเรียกใช้คอนสตรัคเตอร์ที่ไม่มีพารามิเตอร์ นั่นคือ Geek() โดยการเรียกคอนสตรัคเตอร์นี้ผ่าน this() ซึ่งจะทำให้ "Hello! Constructor 1" ถูกพิมพ์ออกมา แล้วจึงจะทำงานในบล็อกของคอนสตรัคเตอร์ของตนเอง และพิมพ์ "Hello! Constructor 2"
output
Hello! Constructor 1
Hello! Constructor 2
ตัวอย่างที่ 2
public Employee(int weeklySalary, int numberOfWeeks)
: this(weeklySalary * numberOfWeeks)
{
}
public Employee(int annualSalary)
{
Salary = annualSalary;
}
จากตัวอย่างนี้ มีการใช้ this เรียกคอนสตรัคเตอร์ที่สอง โดยคอนสตรัคเตอร์แรก ที่มีพารามิเตอร์ 2 ตัว ได้แก่ int weeklySalary และ int numberOfWeeks ซึ่งในคอนสตรัคเตอร์ที่2มี พารามิเตอร์ 1 ตัว จะทำการรับ weeklySalary*numberOfWeeks เข้ามาเป็นค่าพารามิเตอร์ของตัวเองและเมื่อมีการสร้างออบเจ็กต์ในคลาส main
public class Example {
// Main method
static public void Main()
{
// Create object of Employee class
Employee obj = new Employee(5000,4);
}
}
เป็นการสร้างอ็อบเจ็กต์ที่เรียกคอนสตรัคเตอร์ที่มีพารามิเตอร์ นั่นคือ Employee(int weeklySalary, int numberOfWeeks) เมื่อทั้งสองรับค่าพารามิเตอร์ 5000 และ 4 เข้าไปแล้ว ก็จะทำการเรียกใช้ Employee(int annualSalary) โดยใช้ this ซึ่งมีการส่งพารามิเตอร์ไป 1 ตัวคือ ค่า weeklySalary*numberOfWeeks นั่นคือ 20000 ไปยังคอนสตรัคเตอร์ตตัวที่สอง ทำให้ Salary ในคอนสตรัคเตอร์ที่สอง มีค่าเป็น 20000
เปรียบเทียบกับ Python
สิ่งที่คล้ายกับการใช้คีย์เวิร์ด this ใน c#
การใช้ self จะคล้ายกับการใช้ this ในแง่ของการอ้างอิงถึง Instance ปัจจุบันของคลาส
การสร้างและการกำหนดค่าตอนสร้าง instance ซึ่งใน C# เราสามารถ overload constructor เพื่อเรียกใช้ constructure อื่น ในอีก constructure ที่อยู่ในคลาสเดียวกัน ซึ่งคล้ายกับการที่ Python มี __init__()ที่กำหนดค่าตอนสร้าง instance ซึ่งจะใช้วิธีจัดการกับพารามิเตอร์ใน __init__() โดยตรงแทนการ overload constructure
สิ่งที่แตกต่างกัน
Python ไม่มีการ overload constructor เหมือนใน C# แต่ใช้การจัดการพารามิเตอร์และเงื่อนไขใน
__init__()
เพื่อจำลองพฤติกรรมเดียวกันได้การใช้ this ใน C# สามารถใช้เรียก constructor อื่นภายใน class เดียวกันได้ แต่ใน Python ใช้การสร้างเมธอดแยกออกมาต่างหาก หรือการจัดการค่าภายใน __init()__ แทน
ตัวอย่างการใช้ __init__()จำลองพฤติกรรมเดียวกัน
class Dog:
def __init__(self, name, age=None):
self.name = name
if age is not None:
self.age = age
else:
self.age = "Unknown"
def __str__(self):
return f"{self.name} is {self.age} years old"
#ทำการสร้างออบเจ็กต์และแสดงผล
>>> d1 = Dog("Fido", 5) # สร้างออบเจ็กต์ d1 ชื่อ "Fido" และอายุ 5
>>> print(d1)
>>> d2 = Dog("Buddy") # สร้างออบเจ็กต์ d2 ชื่อ "Buddy" และไม่กำหนดอายุ
>>> print(d2)
จากตัวอย่างจะเห็นได้ว่า __init__() เป็นเมธอดที่จะถูกเรียกใช้เมื่อมีการสร้างออบเจ็กต์ของคลาส Dog ซึ่งมีพารามิเตอร์ ได้แก่ self, name และ age โดยเรามีการกำหนดค่าเริ่มต้นของ age ไว้ให้เป็น None ทำให้สามารถสร้างอ็อบเจ็กต์ได้หลากหลายเช่นเดียวกับการ overload constructors ใน C# ซึ่งการใช้ default argument นี้ คล้ายกับการใช้ this ในC# ซึ่งเราสามารถปรับความยืดหยุ่นของการส่งพารามิเตอร์ตอนสร้างออบเจ็กต์ได้ ถ้าเรากำหนดต่า age ก็จะเก็บค่าที่เรากำหนดไว้ในฟิลด์ self.age ถ้าไม่กำหนด ก็จะเป็น Unknown
Output
Fido is 5 years old
Buddy is Unknown years old
เปรียบเทียบกับ Java
ใน Java เราสามารถใช้ this ได้เหมือนๆกันกับ C# โดยระหว่างการoverloading คอนสตรัคเตอร์ จะใช้ this ในการเรียกคอนสตรัคเตอร์ที่ไม่มีพารามิเตอร์ (default constructure) โดยอัตโนมัติจากคอนสตรัคเตอร์ที่มีพารามิเตอร์
ตัวอย่างการใช้ this
เป็นอาร์กิวเมนต์ในคอนสตรัคเตอร์
this
เป็นอาร์กิวเมนต์ในคอนสตรัคเตอร์// Java program to illustrate role of this() in
// Constructor Overloading
public class Box {
double width, height, depth;
int boxNo;
// constructor used when all dimensions and
// boxNo specified
Box(double w, double h, double d, int num)
{
width = w;
height = h;
depth = d;
boxNo = num;
}
// constructor used when no dimensions specified
Box()
{
// an empty box
width = height = depth = 0;
}
// constructor used when only boxNo specified
Box(int num)
{
// this() is used for calling the default
// constructor from parameterized constructor
this();
boxNo = num;
}
public static void main(String[] args)
{
// create box using only boxNo
Box box1 = new Box(1);
// getting initial width of box1
System.out.println(box1.width);
}
}
จากตัวอย่างจะเห็นได้ว่า
Class Box มี คอนสตรัคเตอร์อยู่ 3 ตัว
คอนสตรัคเตอร์ที่มีพารามิเตอร์ ได้แก่ Box(double w, double h, double d, int num) ใช้กำหนดความกว้าง, ความสูง, ความลึก, และหมายเลขกล่องทั้งหมด
คอนสตรัคเตอร์ที่ไม่มีพารามิเตอร์ ได้แก่ Box() ที่เป็นกล่องเปล่า (width, height และ dept มีค่าเป็น 0)
คอนสตรัคเตอร์ Box(int num) มีการเรียกใช้งานคอนสตรัคเตอร์ที่ไม่มีพารามิเตอร์ ด้วยคำสั่ง this() เพื่อให้ออบเจ็กต์ที่สร้างมีค่า width, height และ dept เป็น 0 ก่อนที่จะตั้งค่าหมายเลขกล่อง.
Main
ในส่วนของ main จะมีการสร้างอ็อบเจ็กต์ Box box1 = new Box(1); ซึ่งจะทำการเรียกคอนสตรัคเตอร์ที่มีพารามิเตอร์ 1 ตัว คือ Box(int num) ซึ่งใช้ this() เพื่อเรียกคอนสตรัคเตอร์ที่ไม่มีพารามิเตอร์ก่อน นั่นคือ Box() เพื่อให้แน่ใจว่าค่าต่างๆถูก set เป็นกล่องเปล่าเมื่อรันโปรแกรมก็จะได้ output ดังนี้
0.0
เปรียบเทียบกับภาษา C
ในภาษา C นั้นไม่มีแนวคิดของ constructor แบบเดียวกับที่มีใน C# เพราะภาษา C เป็นภาษาเชิงโครงสร้าง (procedural programming language) ซึ่งไม่ได้รองรับการเขียนโปรแกรมเชิงวัตถุ (OOP) โดยตรงแนวคิดเกี่ยวกับการเรียกใช้ overloaded constructor หรือการใช้ this จึงไม่มีอยู่ในภาษา C
เปรียบเทียบกับ C++
ใน C++ constructor delegation ช่วยให้ constructor หนึ่งสามารถเรียก constructor อื่นภายในคลาสเดียวกันได้ ซึ่งจะช่วยหลีกเลี่ยงการเขียนโค้ดซ้ำซ้อน ทำให้โค้ดสะอาดและดูแลรักษาง่ายขึ้น คล้ายกับการใช้ this ในการเรียก overloaded constructor
ตัวอย่างโปรแกรม
// Program to demonstrate constructor delegation
// in C++
#include <iostream>
using namespace std;
class A {
int x, y, z;
public:
A()
{
x = 0;
y = 0;
z = 0;
}
// Constructor delegation
A(int z) : A()
{
this->z = z; // Only update z
}
void show()
{
cout << x << '\n'
<< y << '\n'
<< z;
}
};
int main()
{
A obj(3);
obj.show();
return 0;
}
จากตัวอย่างจะเห็นได้ว่า คลาสนี้มีคอนสตรัคเตอร์อยู่สองตัว คือ Constructor A(): กำหนดค่าเริ่มต้นให้ตัวแปร x, y, และ z เป็น 0. และ Constructor ที่ใช้การ delegation A(int z) ซึ่งจะทำการเรียก A() ผ่านการใช้ : A()
ก่อนที่จะทำการกำหนดค่า z ด้วยค่าที่ได้รับจากพารามิเตอร์
การทำงานของโปรแกรม
เมื่อเราเรียก A obj(3);
จะทำการเรียก constructor ที่รับพารามิเตอร์ คือ A(int z)
ซึ่ง constructor นี้จะเรียก A()
ผ่านการใช้ : A()
เพื่อกำหนดค่าเริ่มต้นให้ตัวแปร x
, y
, และ z
เป็น 0 จากนั้นจึงจะอัพเดทค่าของ z เป็น 3 และเรียก obj.show();
แสดงค่าของ x
, y
, และ z
Output
0
0
3
Video
Presentation
อ้างอิง
GeeksforGeeks, (27 August 2021), ข้อสำคัญของการใช้ this ,Syntax และตัวอย่างโปรแกรม ตัวอย่างที่1 https://www.geeksforgeeks.org/invoking-an-overloaded-constructor-using-this-keyword-in-c-sharp/
Microsoft,(3 December 2024), ตัวอย่างโปรแกรม ตัวอย่างที่2 ,การเรียกคอนสตรัคเตอร์ด้วย this,https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/using-constructors
David Amos, (2023),เปรียบเทียบกับPythonhttps://realpython.com/python3-object-oriented-programming/#reader-comments
Python Software Foundation,(11 October 2024),ตัวอย่างการใช้__init__(),https://docs.python.org/3/tutorial/classes.html
GeeksforGeeks,(16 Jun 2023),เปรียบเทียบกับ Java,https://www.geeksforgeeks.org/constructor-overloading-java/
GGeeksforGeeks,(23 Jul, 2021),เปรียบเทียบกับ C++,https://www.geeksforgeeks.org/constructor-delegation-c/
Last updated