тип против интерфейса: зачем печатать тогда? - PullRequest
4 голосов
/ 08 января 2010

Расширяя свой кругозор с помощью javascript и опыта работы с Python, я задумался.

Какова цель типа, если видение сущности для внешнего клиента через его интерфейс?

В статических типизированных языках тип имеет очень сильное, центральное значение. Тип и интерфейс строго связаны. Например, в java, когда вы объявляете интерфейс FooIface и объект реализует этот интерфейс, вы не можете использовать его в контексте, требующем BarIface, даже если оба они в точности совпадают с точки зрения методов, подписей и исключений.

Не так в питоне. Даже если два объекта имеют совершенно разные и несвязанные типы, при условии, что их интерфейс одинаков, они полностью и прозрачно взаимозаменяемы. Если он крякает и ходит как утка, это утка. Я могу полностью изменить природу объекта, полностью изменив его интерфейс во время выполнения, но он сохранит исходный тип.

Эта точка зрения доведена до крайности в javascript, где каждый объект в любой цепочке прототипов - это просто объект. Вы спрашиваете тип каждого объекта в javascript, и он скажет вам только, что это объект.

Мне кажется, что понятие типа для этих языков находится на пределе тщетности. Для чего тогда действительно жизненно важно? Имеет ли тип реальное значение в динамически типизированных языках?

Ответы [ 3 ]

1 голос
/ 08 января 2010

Я склонен понимать слово «тип» как эквивалентное слову «класс» в Python. Это только на 99% правильно, но достаточно близко.

>>> type(object)
<type 'type'>
>>> class X(object):
...  pass
... 
>>> type(X)
<type 'type'>
>>> type(_)
<type 'type'>
>>> type(X())
<class '__main__.X'>
>>> type(X) is type(type)
True

Однако в этом случае я обычно избегаю слова «тип». В общем, мой взгляд на это так: слово «тип» подразумевает, что рассматриваемая вещь не является объектом первого класса.

1 голос
/ 08 января 2010

Если язык учитывает только реализованные методы класса, чтобы определить, каким интерфейсам он соответствует, вы можете реализовать интерфейс случайно. Допустим, в Java есть интерфейсы IA и IB , которые определяют метод long getRemainingTime . В этом случае в контракте этих интерфейсов будет указано, какой формат они будут возвращать (один может вернуть время в секундах, а другой - в миллисекундах). Также контекст, в котором используются эти интерфейсы, может сильно отличаться. Допустим, они не называются IA и IB , а IProgress и IStopWatch . В таком случае возвращаемое время будет иметь совершенно разные значения. Если вы смогли поменять эти два интерфейса по своему усмотрению, вы можете получить действительно неожиданные результаты.

В общем случае тип можно рассматривать как вспомогательное средство для выполнения элементарного статического анализа кода. Если вы реализуете определенный интерфейс, то компилятор может сразу сказать вам, что вы, вероятно, допустили ошибку, если попытаетесь передать экземпляр вашей реализации методу, который ожидает аналогичную реализацию, но другого типа.

1 голос
/ 08 января 2010

Я не вижу тщетности. Рассмотрим:

1). Когда вы строите объект

var myThing = new Thing( ... );

Тип вещи имеет значение.

2). Метод Thing можно использовать

this.aProperty

в соответствии с его знанием типа

3). Вы можете использовать instanceof для определения типа

...