Çokbiçimlilik

**Çokbiçimlilik** (**), bir türün bir başka tür gibi davranabilme ve bu tür gibi kullanılabilme özelliğidir. Nesne yönelimli programlama dillerinde çokbiçimlilik özelliği ise aynı temel sınıftan türetilmiş olan sınıflarda paylaşılan, başka bir ifadeyle *aşırı yüklenen* aynı metodun bu sınıflarda farklı şekillerde uyarlanabilmesidir. Nesnenin davranışı çalışma anında belirlendiği için programcılar, çokbiçimlilik özelliği sayesinde nesnelerin türünü önceden bilmek zorunda kalmaz.

## Örnekler

### C++

```cpp
#include <string>
#include <type_traits>
#include <iostream>

struct Animal {
  virtual ~Animal() = default;

  virtual std::string talk() const = 0;
};

struct Cat : public Animal {
  std::string talk() const override { return "Miyav!"; }
};

struct Dog : public Animal {
  std::string talk() const override { return "Hav! Hav!"; }
};

static_assert(std::is_polymorphic_v<Animal>);
static_assert(std::is_base_of_v<Animal, Cat>);
static_assert(std::is_base_of_v<Animal, Dog>);

std::string talk(const Animal& a) {
  return a.talk();
}

int main() {
  Cat minnos;
  Dog karabas;

  std::cout << talk(minnos) << '\n';  // Miyav!
  std::cout << talk(karabas) << '\n'; // Hav! Hav!
}
```


```cpp
// C++17 ve sonrasi std::variant tipi kullanarak
// https://en.cppreference.com/w/cpp/utility/variant
#include <string>
#include <variant>
#include <iostream>

struct Cat {
  std::string talk() const { return "Miyav!"; }
};

struct Dog {
  std::string talk() const { return "Hav! Hav!"; }
};

using Animal = std::variant<Cat, Dog>;

std::string talk(const Animal& a) {
  struct v {
    std::string operator()(const Cat& c) const { return c.talk(); }
    std::string operator()(const Dog& d) const { return d.talk(); }
  };

  return std::visit(v{}, a);
}

int main() {
  Cat minnos;
  Dog karabas;

  std::cout << talk(minnos) << '\n';  // Miyav!
  std::cout << talk(karabas) << '\n'; // Hav! Hav!
}
```


```cpp
// C++17 ve sonrasi std::any tipi kullanarak:
// https://en.cppreference.com/w/cpp/utility/any
#include <string>
#include <any>
#include <iostream>

struct Cat {
  std::string talk() const { return "Miyav!"; }
};

struct Dog {
  std::string talk() const { return "Hav! Hav!"; }
};

std::string talk(const std::any &animal) {
  if (const Cat *c = std::any_cast<Cat>(&animal))
    return c->talk();

  else if (const Dog *d = std::any_cast<Dog>(&animal))
    return d->talk();

  return std::string{};
}

int main() {
  Cat minnos;
  Dog karabas;

  std::cout << talk(minnos) << '\n';  // Miyav!
  std::cout << talk(karabas) << '\n'; // Hav! Hav!
}
```



```cpp
// C++20 auto fonksiyon parametresi kullanarak
#include <string>
#include <iostream>

struct Cat {
  std::string talk() const { return "Miyav!"; }
};

struct Dog {
  std::string talk() const { return "Hav! Hav!"; }
};

std::string talk(const auto &animal) {
  return animal.talk();
}

int main() {
  Cat minnos;
  Dog karabas;

  std::cout << talk(minnos) << '\n';  // Miyav!
  std::cout << talk(karabas) << '\n'; // Hav! Hav!
}
```



```cpp
// C++20 concept ile türü belli üye fonksiyona sahip olacak şekilde kısıtlayarak
// https://en.cppreference.com/w/cpp/language/constraints
#include <string>
#include <iostream>
#include <concepts>

template <typename T>
concept Talkable = requires(T t) {
  { t.talk() } -> std::same_as<std::string>;
};

struct Cat {
  std::string talk() const { return "Miyav!"; }
};

struct Dog {
  std::string talk() const { return "Hav! Hav!"; }
};

std::string talk(const Talkable auto &animal) {
  return animal.talk();
}

int main() {
  Cat minnos;
  Dog karabas;

  std::cout << talk(minnos) << '\n';  // Miyav!
  std::cout << talk(karabas) << '\n'; // Hav! Hav!
}
```


### Java


```java
interface IAnimal {
  String talk();
}

class Cat implements IAnimal {
  public String talk() { return "Miyav!"; }
}

class Dog implements IAnimal {
  public String talk() { return "Hav! Hav!"; }
}

public class Test {
  public static void main(String[] args) {
    IAnimal cat = new Cat();
    IAnimal dog = new Dog();

    System.out.println(cat.talk()); // Miyav!
    System.out.println(dog.talk()); // Hav! Hav!
  }
}
```


## Kaynakça