Ekim 18, 2024

/

What is function overloading?

Function overloading is the process of redefining a function with the same name but different parameter combinations. The compiler or type system determines the correct function to call based on the parameters.

Function overloading in OOP languages

Java ve C++ gibi dillerde overload işlemi doğrudan desteklenir. Derleyici, çağrılan fonksiyonun parametrelerine göre doğru metodu seçer.

Java’da implementasyonu aşağıdaki gibidir:

Terminal window
class Notification {
void send(String email, String message) {
// ...
}
void send(String email, String message, boolean isUrgent) {
// ...
}
void send(String email, String subject, String body) {
// ...
}
}
public class Main {
public static void main(String[] args) {
Notification notifier = new Notification();
notifier.send("Hello!");
notifier.send(
"Reminder",
"The meeting time has been changed to 10 AM."
);
notifier.send(
"ensbaspinar@gmail.com",
"Can you send me the plans for the team?",
true
);
}
}

C++ dilinde de benzer bir implementasyon mevcuttur:

Terminal window
class Notification {
public:
void send(const string& message) {
// ...
}
void send(const string& subject, const string& body) {
// ...
}
void send(const string& email, const string& message, bool isUrgent) {
// ...
}
};
int main() {
Notification notifier;
notifier.send("Hello!");
notifier.send(
"Reminder",
"The meeting time has been changed to 10 AM."
);
notifier.send(
"ensbaspinar@gmail.com",
"Can you send me the plans for the team?",
true
);
}

Bu örneklerde send metodu farklı sayıda ve türde parametrelerle çağrılabilir.

How does function overloading work?

  1. Derleyici, aynı isme sahip fonksiyonların imzalarını kontrol eder. Eğer bu fonksiyonların parametre listeleri farklıysa, derleme başarılı olur; aksi takdirde derleme hatası oluşur.
  2. Aynı isme sahip fonksiyonları ayırt etmek için name mangling tekniğini kullanır. Bu teknik, fonksiyon adlarını parametre sayısı ve türleriyle birlikte kodlayarak benzersiz hale getirir. Örneğin, foo(int, double) ve foo(double, double) fonksiyonlarının isimleri derleyicide foo_id ve foo_dd olarak temsil edilir.
  3. Fonksiyon çağrıldığında derleyici argüman türlerini kontrol eder ve uygun fonksiyonu bulur.

Function overloading in TypeScript

TypeScript doğrudan OOP dilleri gibi overload desteklemez. Tek bir implementasyona birdan fazla imza type’ı tanımlamanızı sağlar.

Example

Terminal window
class Notification {
send(message: string): void;
send(subject: string, body: string): void;
send(email: string, message: string, isUrgent?: boolean): void;
send(arg1: unknown, arg2?: unknown, arg3?: unknown): void {
// İmza send(message: string) ise
if (typeof arg1 === "string" && !arg2 && !arg3) {
// ...
}
// İmza send(subject: string, body: string) ise
else if (typeof arg1 === "string" && typeof arg2 === "string" && !arg3) {
// ...
}
// İmza send(email: string, message: string, isUrgent?: boolean) ise
else if (typeof arg1 === "string" && typeof arg2 === "string" && typeof arg3 === "boolean") {
// ...
}
}
}
const notifier = new Notification();
notifier.send("Hello!");
notifier.send("Hello!");
notifier.send(
"Reminder",
"The meeting time has been changed to 10 AM."
);
notifier.send(
"ensbaspinar@gmail.com",
"Can you send me the plans for the team?",
true
);

Example 2

Geçtiğimiz aylarda şirkettekullandığım ve beni bu hook’u yazmaya iten hook örneğini de eklemiş olayım.

Terminal window
type Callback = () => void;
export function useSeenObserver(callback: Callback): React.RefObject<HTMLElement>;
export function useSeenObserver(selector: string, callback: Callback): void;
export function useSeenObserver(arg1: string | Callback, arg2?: Callback): React.RefObject<HTMLElement> | void {
let element: Element;
let callback: Callback;
let ref = useRef<HTMLElement>(null);
if (typeof arg1 === "string") {
element = document.querySelector(arg1)!;
callback = arg2!;
} else {
element = ref.current!;
callback = arg1!;
}
// ...
if (typeof arg1 !== "string") {
return ref;
}
}

Hook’u kullanırken return ettiğimiz ref’i kullanarak ilgili elementi belirtebilirsiniz.

Terminal window
const ref = useSeenObserver(() => {
// ...
});
return <div ref={ref}></div>;

Ya da aşağıdaki gibi bir selector kullanabilirsiniz.

Terminal window
useSeenObserver("#component", () => {
// ...
});
return <div id="component"></div>;

How does function overloading work?

  1. Fonksiyonun belirtilen imzalardan biriyle uyumlu olup olmadığını görmek için geliştirme ve derleme esnasında tür kontrolleri yapılarak uyarır.
  2. Typescript, JavaScript’e derlendiğinden dolayı type safety ve signature check işlemleri runtime’da çalışmaz. Bu sebepten ötürü fonksiyonun içerisinde parametre türlerinin koşullarla kontrol edilir.

Why should I use it?

Aynı fonksiyonu union type ile tanımlamak da mümkündür ve bu sebeple neden signature kullanmalıyım sorusu aklınıza gelebilir. Son örneği signature kullanmadan yeniden yazalım.

Terminal window
type Callback = () => void;
export function useSeenObserver(arg1: string | Callback, arg2?: Callback): React.RefObject<HTMLElement> | void {
let element: Element;
let callback: Callback;
let ref = useRef<HTMLElement>(null);
if (typeof arg1 === "string") {
element = document.querySelector(arg1)!;
callback = arg2!;
} else {
element = ref.current!;
callback = arg1!;
}
// ...
if (typeof arg1 !== "string") {
return ref;
}
}

Bu implementasyonu kullandığımızda TypeScript’in önerdiği tipe ve yaptığı kontrole görseldeki gibidir.

Görebileceğiniz üzere net bir template gösteremez. Argüman isimleri ve hangi parametrenin hangisiyle birlikte kullanılabileceği bulanıklaşır. Aşağıdaki hiçbir kombinasyonda TypeScript hata vermez:

  • (arg1: string) -> hatalı kullanım
  • (arg1: string, arg2: Callback) -> doğru kullanım
  • (arg1: Callback) -> doğru kullanım
  • (arg1: Callback, arg2: Callback) -> hatalı kullanım

Signature kullandığınızda ise aşağıdaki gibi doğru bir API elde etmiş olursunuz.

Function overloading, özellikle büyük projelerde hatalara karşı dayanıklı bir API tasarımı sağlar. Ama OOP dillerine göre manual kontrollere güvenir ve kodu kirletir. Bu pattern ile genelde çok fazla karşılaşılmaz.

Diğer yazılarda buluşalım 👋