Page cover image

Overloading of Constructors

ณัฐฌา อย่าเคลิ้มจิตร์ 650710542

Constructor Overloading

มีความคล้ายๆกับ Method Overloading คือการสร้าง constructor หลายตัวในคลาสเดียวกัน แต่มีพารามิเตอร์ที่แตกต่างกัน ซึ่งช่วยให้เราสามารถเรียกใช้งาน constructor ที่แตกต่างกันตามลักษณะของข้อมูลที่เราส่งเข้ามาได้ อาจจะต่างกันที่จำนวนของพารามิเตอร์ หรือ ชนิดของพารามิเตอร์ โดย constructor แต่ละตัว จะถูกเลือกใช้งานตามประเภทของพารามิเตอร์ที่ส่งเข้ามาเมื่อสร้าง object

Ambiguous overloads

เกิดขึ้นเมื่อคอมไพเลอร์ไม่สามารถตัดสินได้ว่าจะเรียกใช้ constructor ตัวใดที่ถูกต้อง เนื่องจากมี constructor ที่มีชื่อเดียวกันหลายตัว แต่ลักษณะของพารามิเตอร์ที่ส่งเข้ามาทำให้คอมไพเลอร์ไม่สามารถแยกแยะได้อย่างชัดเจนว่าควรเลือกใช้อันไหน

ตัวอย่าง

using System;

class Example
{
    public Example(int a)
    {
        Console.WriteLine("Constructor with int");
    }
    
    public Example(double a)
    {
        Console.WriteLine("Constructor with double");
    }
}

class Program
{
    static void Main()
    {
        Example ex = new Example(5.0f); // Ambiguous overload
    }
}

ในตัวอย่างนี้ constructor ตัวแรก Example(int a) รับพารามิเตอร์ประเภท int และ constructor ตัวที่สอง Example(double a) รับพารามิเตอร์ประเภท double เมื่อเราสร้างอินสแตนซ์ Example โดยส่งค่า 5.0f ซึ่งเป็นค่า float คอมไพเลอร์สามารถแปลงค่า float เป็น int ได้โดย implicit conversion เพื่อใช้คอนสตรัคเตอร์ตัวแรก และ ใน double ก็สามารถทำได้เช่นกัน เนื่องจากทั้งสอง constructor สามารถรับค่าที่ส่งเข้ามาได้ทั้งคู่ คอมไพเลอร์จึงไม่สามารถเลือก constructor ที่เหมาะสมได้ ทำให้เกิดปัญหา Ambiguous Overload ขึ้น

วิธีแก้ปัญหา

//เป็นการบังคับให้ใช้ constructor ที่รับค่าเป็น int
Example ex = new Example((int)5.0f);
//เพิ่ม constructor ที่รับค่าเป็นชนิดข้อมูลที่ต้องการ
 public Example(float a)
        {
        Console.WriteLine("Constructor with float");
        }

ประโยชน์ของ Overloading Constructor

การใช้ overloading constructor เป็นการเพิ่มความยืดหยุ่นให้กับ class โดยสามารถสร้าง objects ที่พร้อมใช้งานในสถานะต่างๆ โดยไม่ต้องกำหนดค่าผ่าน method อื่นๆ หลังจากสร้าง object นอกจากนี้ยังช่วยลดความซับซ้อนของโค้ดและลดโอกาสในการเกิดข้อผิดพลาด

ตัวอย่างการ Overloading Constructor

1.By changing the number of the parameters

using System;
 
class Multiple {
    int x, y;
    int f, p, s;
    public Multiple(int a, int b)
    {
        x = a;
        y = b;
    }
    public Multiple(int a, int b, int c)
    {
        f = a;
        p = b;
        s = c;
    }
    public void show()
    {
        Console.WriteLine("Fisrt constructor (int * int): {0} ",  (x * y));
    }
    public void show1()
    {
        Console.WriteLine("Second constructor (int * int * int): {0}", (f * p * s));
    }
}
class Mul {
    static void Main()
    {
        Multiple g = new Multiple(10, 20);
        g.show();
        Multiple q = new Multiple(10, 20, 30);
        q.show1();
    }
}

จากตัวอย่าง คลาสนี้มีชื่อว่า Multiple ซึ่งมี constructor สองตัว ใน constructor ตัวแรกมีพารามิเตอร์ 2 ตัว และใน constructor ตัวที่สองมีพารามิเตอร์ 3 ตัว ซึ่งประเภทของข้อมูลของ constructor ทั้งสองตัวเป็น int เหมือนกันทุกตัว จึงต่างกันแค่จำนวนของพารามิเตอร์

2.By changing the Data types of the parameters

using System;
 
class ADD {
    int x, y;
    double f;
    string s;
    
    public ADD(int a, double b)
    {
        x = a;
        f = b;
    }
     public ADD(int a, string b)
    {
        y = a;
        s = b;
    }
    public void show()
    {
        Console.WriteLine("First constructor (int + float): {0} ", (x + f));
    }
    public void show1()
    {
        Console.WriteLine("Second constructor (int + string): {0}",  (s + y));
    }
}

class A {
    static void Main()
    {
        ADD g = new ADD(20, 10.5);
        g.show();
        ADD q = new ADD(10, "The value of y is ");
        q.show1();
    }
}

จากตัวอย่าง คลาสนี้มีชื่อว่า ADD ใน constructor ตัวแรกมีพารามิเตอร์เป็น int และ double ส่วน constructor ตัวที่สอง มีพารามิเตอร์เป็น int และ string ซึ่งจะเห็นได้ว่าจำนวนของพารามิเตอร์เท่ากัน แต่ชนิดของพารามิเตอร์ต่างกัน

3.By changing the Order of the parameters

using System;
 
class student {
        public string name;
	public double height;
	public double weight;

    public student(string n, double h, double w)
    {
        name = n;
        height = h;
        weight = w;
    }
    public student(double h, double w, string n)
    {
        height = h;
        weight = w;
        name = n;
    }
    public void show()
    {
        Console.WriteLine("Name : " + name);
        Console.WriteLine("Height : " + height + " cm.");
        Console.WriteLine("Weight : " + weight + " kg.");
    }
}
class std {
     
    static void Main()
    {
        student s1 = new student("Natcha", 164.5 , 75.6);
        student s2 = new student(183.3, 69.2, "Thanakorn");
         
        Console.WriteLine("First Constructor: ");
        s1.show();
 
        Console.WriteLine();
 
        Console.WriteLine("Second Constructor: ");
        s2.show();
         
    }
}

จากตัวอย่าง คลาสนี้มีชื่อว่า student จะเห็นได้ว่ามี constructor สองตัว ทั้งสองตัวมีพารามิเตอร์ที่ชนิดตัวแปรเหมือนกัน แต่ลำดับต่างกัน คอมไพเลอร์ก็จะเรียกใช้ constructor ตามลำดับของพารามิเตอร์

4.Invoke an Overloaded Constructor using “this” keyword

using System;

class volume {
	private int Length, Height;
	private double Width;
	public volume()
	{
		Console.WriteLine("Default Constructor");
	}
	public volume(int l, double w) : this()
	{
		Console.WriteLine("Second Constructor");
		Length = l;
		Width = w;
	}
	public volume(int l, double w, int h) : this(l, w)
	{
		Console.WriteLine("Third Constructor");
		Height = h;
	}
	public double result()
	{
		return (Length * Width * Height);
	}
}

class VL {
	public static void Main()
	{
		volume g = new volume(20, 40.5, 60);
		Console.WriteLine("Volume is : {0}", g.result());
	}
}

จากตัวอย่าง คลาสนี้มีชื่อว่า volume ซึ่งมี constructor สามตัว ประกอบด้วย

First parameters

  • เป็น default constructor คือไม่มีพารามิเตอร์

  • จะถูกเรียกเมื่อสร้าง object volume โดยไม่ส่งค่าอะไรเข้าไป

  • และจะพิมพ์ข้อความว่า "Default Constructor"

Second parameters

  • รับพารามิเตอร์สองตัวคือ int กับ double

  • มีการใช้ this() เป็นการเรียก default constructor ก่อนจะทำงานของตัวมันเอง จะทำให้ข้อความ "Default Constructor " ถูกพิมพ์ออกมาก่อน แล้วตามด้วยข้อความ "Second Constructor"

  • จะถูกเรียกใช้เมื่อมีการสร้าง object volume ที่รับค่า (int,double)

Third parameters

  • รับพารามิเตอร์สามตัว คือ int,double และ int

  • มีการใช้ this(l, w) เพื่อเรียก Constructor ที่สอง ซึ่งจะทำการพิมพ์ข้อความ "Second Constructor" ตามด้วยข้อความ "Third Constructor"

  • จะถูกเรียกใช้เมื่อมีการสร้าง object volume ที่รับค่า (int,double,int)

ใน Method Main มีการสร้างobject ของคลาส volume ชื่อ g ด้วยพารามิเตอร์ 3 ตัว (20, 40.5, 60) เป็นการเรียกใช้ constructor ที่มีพารามิเตอร์ 3 ตัว constructor นี้จะเรียกใช้ constructor ที่มีพารามิเตอร์ 2 ตัวก่อน โดยผ่าน this(l, w) constructor ที่มีพารามิเตอร์ 2 ตัวก็จะเรียกใช้ constructor ที่ไม่มีพารามิเตอร์ก่อนผ่าน this() หลังจากนั้นจึงกำหนดค่าให้กับ Length, Width และ Height ตามลำดับ และคำนวณปริมาตรจากการเรียกใช้ g.result()

Constructor Overloading ใน C# ต่างจากภาษาอื่นอย่างไร?

C#

using System;

class Employee
{
    public string Name;
    public int Id;
    public int Age;
    public string Position;
    public Employee()
    {
        Name = "Unknown";
        Id = 0;
        Age = 0;
        Position = "Not Assigned";
    }
    public Employee(string name, int id)
    {
        Name = name;
        Id = id;
        Age = 0;
        Position = "Not Assigned";
    }

    public Employee(string name, int id, int age, string position)
    {
        Name = name;
        Id = id;
        Age = age;
        Position = position;
    }
}
class emp
{
    static void Main()
    {
        Employee emp1 = new Employee(); 
        Employee emp2 = new Employee("somjai", 101); 
        Employee emp3 = new Employee("somdej", 102, 30, "Manager"); 

        Console.WriteLine($"{emp1.Name}, {emp1.Id}, {emp1.Age}, {emp1.Position}");
        Console.WriteLine($"{emp2.Name}, {emp2.Id}, {emp2.Age}, {emp2.Position}");
        Console.WriteLine($"{emp3.Name}, {emp3.Id}, {emp3.Age}, {emp3.Position}");
    }
}

Java

ในภาษา java การ overloading constructor คล้ายกับ C# โดย constructor แต่ละตัวจะต้องมีพารามิเตอร์ที่แตกต่างกัน

class Employee {
    String name;
    int id;
    int age;
    String position;

    Employee() {
        name = "Unknown";
        id = 0;
        age = 0;
        position = "Not Assigned";
    }

    Employee(String name, int id) {
        this.name = name;
        this.id = id;
        this.age = 0;
        this.position = "Not Assigned";
    }

    Employee(String name, int id, int age, String position) {
        this.name = name;
        this.id = id;
        this.age = age;
        this.position = position;
    }

    public void display() {
        System.out.println(name + ", " + id + ", " + age + ", " + position);
    }
}

public class emp {
    public static void main(String[] args) {
        Employee emp1 = new Employee();
        Employee emp2 = new Employee("somjai", 101); 
        Employee emp3 = new Employee("somdej", 102, 30, "Manager");

        emp1.display();
        emp2.display();
        emp3.display();
    }
}

Python

ในภาษา Python constructor ถูกกำหนดโดยใช้ฟังก์ชัน __init__ และการ overload constructor จะทำได้โดยการกำหนดพารามิเตอร์เริ่มต้นให้กับฟังก์ชัน __init__

class Employee:
    def __init__(self, name="Unknown", id=0, age=0, position="Not Assigned"):
        self.name = name
        self.id = id
        self.age = age
        self.position = position

emp1 = Employee() 
emp2 = Employee("somjai", 101)  
emp3 = Employee("somdej", 102, 30, "Manager")

print(f"{emp1.name}, {emp1.id}, {emp1.age}, {emp1.position}")
print(f"{emp2.name}, {emp2.id}, {emp2.age}, {emp2.position}")
print(f"{emp3.name}, {emp3.id}, {emp3.age}, {emp3.position}")

C

ในภาษา C ไม่มีแนวคิดของ Constructor Overloading เพราะ C เป็นภาษาที่ไม่มีการสนับสนุน OOP แต่สามารถสร้างฟังก์ชันที่ทำหน้าที่คล้ายกับ constructor และทำการ overload ได้

#include <stdio.h>
#include <string.h>

typedef struct {
    char name[50];
    int id;
    int age;
    char position[50];
} Employee;

void initEmployee(Employee* emp) {
    strcpy(emp->name, "Unknown");
    emp->id = 0;
    emp->age = 0;
    strcpy(emp->position, "Not Assigned");
}
void initEmployeeWithParams(Employee* emp, const char* name, int id) {
    strcpy(emp->name, name);
    emp->id = id;
    emp->age = 0;
    strcpy(emp->position, "Not Assigned");
}
void initEmployeeFull(Employee* emp, const char* name, int id, int age, const char* position) {
    strcpy(emp->name, name);
    emp->id = id;
    emp->age = age;
    strcpy(emp->position, position);
}
int main() {
    Employee emp1, emp2, emp3;

    initEmployee(&emp1); 
    initEmployeeWithParams(&emp2, "somjai", 101); 
    initEmployeeFull(&emp3, "somdej", 102, 30, "Manager"); 

    printf("%s, %d, %d, %s\n", emp1.name, emp1.id, emp1.age, emp1.position);
    printf("%s, %d, %d, %s\n", emp2.name, emp2.id, emp2.age, emp2.position);
    printf("%s, %d, %d, %s\n", emp3.name, emp3.id, emp3.age, emp3.position);

    return 0;
}

Slide

Reference

ความหมายของการ Overloading Constructor, ตัวอย่างการ Overloading Constructor
Ambiguous overloads
ประโยชน์ของการ overloading constructor, overloading constructor ในภาษา java
overloading constructor ในภาษา C
overloading constructor ในภาษา Python

Last updated