IMHO, преимущество утиного ввода становится более значительным, если вы придерживаетесь некоторых соглашений, например, последовательно именовать переменные и методы. На примере из Кен G, я думаю, что это будет читать лучше:
class SimpleResults {
def mapOfListResults
def total
def categories
}
Допустим, вы определяете контракт на какой-то операции под названием "calculateRating (A, B) где А и В придерживаются другого договора. В псевдокоде, он будет читать:
Long calculateRating(A someObj, B, otherObj) {
//some fake algorithm here:
if(someObj.doStuff('foo') > otherObj.doStuff('bar')) return someObj.calcRating());
else return otherObj.calcRating();
}
Если вы хотите реализовать это в Java, как А и В должны реализовать некий интерфейс, который читает что-то вроде этого:
public interface MyService {
public int doStuff(String input);
}
Кроме того, если вы хочу обобщать вам контракт для расчета рейтингов (скажем, у вас есть еще один алгоритм для рейтинговых расчетов), вы также должны создать интерфейс:
public long calculateRating(MyService A, MyServiceB);
с утиной типизации, вы можете d itch your интерфейсы и просто полагайтесь на то, что во время выполнения оба A и B правильно ответят на ваши вызовы doStuff()
. Нет необходимости в конкретном определении контракта. Это может работать для вас, но оно также может работать против вас.
Недостатком является то, что вы должны быть особенно осторожны, чтобы гарантировать, что ваш код не сломается, когда другие его изменят (т. Е. Другой человек должен знать о неявном контракте на имя и аргументы метода) ,
Обратите внимание, что это особенно усугубляется в Java, где синтаксис не такой уж краток, как он мог бы быть (по сравнению с Scala, например). Противоположным примером является Lift framework, где они говорят, что количество SLOC фреймворка аналогично Rails, но тестовый код имеет меньше строк, потому что им не нужно реализовывать проверки типов в рамках тестов.
Duck типирование и статической типизации являются ортогональными понятиями. – 2010-12-14 15:53:13