Неявна типізація, латентна типізація або качина типізація (калька з ) — різновид динамічної типізації, застосовуваної в деяких мовах програмування, коли межі використання об'єкта визначаються його поточним набором методів і властивостей, на противагу успадкуванню від певного класу. Тобто вважається, що об'єкт реалізує інтерфейс, якщо він містить всі методи цього інтерфейсу, незалежно від зв'язків в ієрархії наслідування та приналежності до якогось конкретного класу.

Назва терміна походить від англійського «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# мають додаткову анотацію типів, котра інструктує компілятор розміщувати перевірку типів і класів на стадії виконання, а не під час компіляції, і включати код для перевірки типів у відкомпільований вивід.

Інші мови зі статичною типізацією, наприклад F#, підтримують статичну качину типізацію, коли типи перевіряються на наявність певних сигнатур методів під час компіляції.

Виноски

Посилання