Качина типізація
Неявна типізація, латентна типізація або качина типізація (калька з англ. Duck typing) — різновид динамічної типізації, застосовуваної в деяких мовах програмування, коли межі використання об'єкта визначаються його поточним набором методів і властивостей, на противагу успадкуванню від певного класу. Тобто вважається, що об'єкт реалізує інтерфейс, якщо він містить всі методи цього інтерфейсу, незалежно від зв'язків в ієрархії наслідування та приналежності до якогось конкретного класу.
Назва терміна походить від англійського «duck test» («качиний тест»), який в оригіналі звучить так:
- «If it looks like a duck, swims like a duck and quacks like a duck, then it probably is a duck».
- («Якщо воно виглядає як качка, плаває як качка і крякає як качка, то це напевно і є качка»).
Качина типізація вирішує такі проблеми ієрархічної типізації як:
- неможливість явно вказати (шляхом наслідування) на сумісність інтерфейсу з усіма справжніми і майбутніми інтерфейсами, з якими він ідейно сумісний;
- експоненціальне збільшення числа зв'язків в ієрархії типів при хоча б частковій спробі це зробити.
Іншим близьким підходом є структурні підтипи в OCaml, де типи об'єктів сумісні, якщо сумісні сигнатури їхніх методів, незалежно від оголошеного наслідування, причому все це перевіряється під час компіляції програми.
Приклади концепції
Розглянемо такий псевдо-код мови з качиною типізацією:
function calculate(a, b, c) => return (a+b)*c example1 = calculate (1, 2, 3) example2 = calculate ([1, 2, 3], [4, 5, 6], 2) example3 = calculate ('apples ', 'and oranges, ', 3) print to_string example1 print to_string example2 print to_string example3
У цьому прикладі кожного разу викликається функція calculate
з об'єктами без спорідненої спадковості — числа, списки, рядки. Оскільки об'єкти підтримують методи «+» та «*», функція буде виконана. Якщо код, приміром, виконуватиметься у Ruby або Python, результатом буде
9 [1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6] apples and oranges, apples and oranges, apples and oranges,
Таким чином, качина типізація дозволяє поліморфізм без успадкування. Єдиним обмеженням на функцію calculate
є здатність її аргументів застосовувати методи «+» та «*».
На Python
Перевірка на качку може бути ілюстрована такими кодами.
В цьому прикладі Sparrow
є качкою.
Приклад без успадкування |
---|
class Duck:
def fly(self):
print("Качка літає")
class Sparrow:
def fly(self):
print("Горобець літає")
class Whale:
def swim(self):
print("Кит плаває")
a, b ,c = Duck(), Sparrow(), Whale()
for animal in a, b, c:
animal.fly()
Результат: Качка літає
Горобець літає
AttributeError: 'Whale' object has no attribute 'fly'
|
В цьому прикладі розглядається функція in_the_forest
(у_лісі), згідно якого об'єкти Human
і Dog
є качками:
Приклад з успадкуванням |
---|
class Animal(object):
def __init__(self, name):
self.name = name
def speak(self):
pass
class Duck(Animal):
def speak(self):
return self.quack()
def quack(self):
return "Кря!"
def feathers(self):
return "має біле та сіре пір'я."
class Dog(Animal):
def speak(self):
return self.woof()
def woof(self):
return "Гав!"
def feathers(self):
return "може знайти пір'я у лісі."
class Human(Animal):
def speak(self):
return "Привіт!"
def feathers(self):
return "не має пір'я."
def in_the_forest(duck):
print(duck.name + " каже " + duck.speak() + " і " + duck.feathers())
def game():
animal_a = Duck("Дональд")
animal_b = Dog("Сірко")
animal_c = Human("Іван")
for animal in animal_a, animal_b, animal_c:
in_the_forest(animal)
game()
Результат: Дональд каже Кря! і має біле та сіре пір'я.
Іван каже Привіт! і не має пір'я.
Сірко каже Гав! і може знайти пір'я у лісі. |
У мовах зі статичною типізацією
Іноді мови зі статичною типізацією, такі як Boo чи версія 4 випуску C# мають додаткову анотацію типів[1][2], котра інструктує компілятор розміщувати перевірку типів і класів на стадії виконання, а не під час компіляції, і включати код для перевірки типів у відкомпільований вивід.
Інші мови зі статичною типізацією, наприклад F#, підтримують статичну качину типізацію, коли типи перевіряються на наявність певних сигнатур методів під час компіляції.
Виноски
- Boo: Duck Typing. Архів оригіналу за 6 жовтня 2008. Процитовано 9 січня 2014.
- Anders Hejlsberg Introduces C# 4.0 at PDC 2008