среда, 5 ноября 2014 г.

Ссылка. Типы данных наносят ответный удар

http://habrahabr.ru/company/mailru/blog/242305/

Хорошая по-моему статья. Очень полезная. Даже не в плане Python'а. А вообще "для мозгов".

С моими представлениями (в частности с - "Массивы, списки иитераторы") по-крайней мере - "совпадает". Хотя в статье про "итераторы" - как раз ничего и не сказано. Но всё равно - "на волне".

Процитирую:

"

Что такое «cистема типов»?

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

Я не буду слишком углубляться в систему типов по двум причинам. Во-первых, я сам не до конца понимаю эту область, а во-вторых, на самом деле совсем необязательно понимать всё, чтобы «почувствовать» взаимосвязи между типами данных. Для меня важно учитывать их поведение потому, что это влияет на архитектуру интерфейсов, и я буду рассказывать о типизации не как теоретик, а как практик (на примере построения красивого API).

Системы типов могут иметь множество характеристик, но самое важное различие между ними состоит в том количестве информации, которое о себе предоставляет тип данных, когда вы пытаетесь с ним работать.

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

Однако есть одна вещь, которая отсутствует в Python: составные типы данных. Все типы данных в Python примитивны, и это означает, что в определённый момент времени вы можете работать только с одним из них, в отличие от составных типов.

Самый простой составной тип данных, который есть в большинстве языков программирования — структуры. В Python их, как таковых, нет, однако во многих случаях библиотекам необходимо определять собственные структуры, например, модели ORM в Django и SQLAlchemy. Каждый столбец в базе данных представлен через дескриптор Python, который соответствует полю в структуре, и когда вы говорите, что primary key называется id, и это IntegerField(), вы определяете модель как составной тип данных.

Составные типы не ограничены только структурами. Когда вам нужно работать больше, чем с одним числом, вы используете коллекции (массивы). В Python для этого есть списки, и каждый элемент списка может иметь совершенно произвольный тип данных, в противоположность спискам в других языках программирования, имеющих заданный тип элемента (например, список целочисленных).
"

"Словосочетание «список целочисленных» всегда имеет больший смысл, чем просто список. Вы можете с этим поспорить, ведь всегда можно пройтись по списку и посмотреть тип каждого элемента, однако что делать с пустым списком? Когда в Python у вас есть пустой список, вы не можете определить тип его данных.

Такая же проблема возникает при использовании значения None. Допустим, у вас есть функция, которая принимает аргумент “Пользователь”. Если вы передаёте в неё параметр None, вы никогда не узнаете, что это должен был быть объект типа «Пользователь».

Какое же решение этой проблемы? Не иметь нулевых указателей и иметь массивы с явно указанными типами элементов. Всем известно, что в Haskell всё так и есть, однако есть другие, менее враждебные к разработчикам языки. Например, Rust — язык программирования, более близкий и понятный нам, поскольку он очень похож на C++. И в Rust есть очень мощная система типов."

И ещё:

"

Что такое сабкласс

Приведённый выше пример показывает нам, что в Python может быть класс, который наследуется от другого класса, но при этом его поведение не будет соответствовать базовому классу. И это важная проблема, если мы говорим о статической типизации. Так, в Python 3 вы не можете реализовать интерфейс для типа dict до тех пор, пока не напишете его на C. Причина такого ограничения в том, что этот тип диктует видимым объектам поведение, которое попросту не может быть реализовано. Это невозможно.

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

Вот с чем "перекликается":

NSString

Опять процитирую:

"

Subclassing Notes

It is possible to subclass NSString (and NSMutableString), but doing so requires providing storage facilities for the string (which is not inherited by subclasses) and implementing two primitive methods. The abstractNSString and NSMutableString classes are the public interface of a class cluster consisting mostly of private, concrete classes that create and return a string object appropriate for a given situation. Making your own concrete subclass of this cluster imposes certain requirements (discussed in Methods to Override).
Make sure your reasons for subclassing NSString are valid. Instances of your subclass should represent a string and not something else. Thus the only attributes the subclass should have are the length of the character buffer it’s managing and access to individual characters in the buffer. Valid reasons for making a subclass of NSString include providing a different backing store (perhaps for better performance) or implementing some aspect of object behavior differently, such as memory management. If your purpose is to add non-essential attributes or metadata to your subclass of NSString, a better alternative would be object composition (see Alternatives to Subclassing). Cocoa already provides an example of this with theNSAttributedString class.

Methods to Override

Any subclass of NSString must override the primitive instance methods length and characterAtIndex:. These methods must operate on the backing store that you provide for the characters of the string. For this backing store you can use a static array, a dynamically allocated buffer, a standard NSString object, or some other data type or mechanism. You may also choose to override, partially or fully, any other NSStringmethod for which you want to provide an alternative implementation. For example, for better performance it is recommended that you override getCharacters:range: and give it a faster implementation.
You might want to implement an initializer for your subclass that is suited to the backing store that the subclass is managing. The NSString class does not have a designated initializer, so your initializer need only invoke the init method of super. The NSString class adopts the NSCopyingNSMutableCopying, and NSCodingprotocols; if you want instances of your own custom subclass created from copying or coding, override the methods in these protocols.

Alternatives to Subclassing

Often a better and easier alternative to making a subclass of NSString—or of any other abstract, public class of a class cluster, for that matter—is object composition. This is especially the case when your intent is to add to the subclass metadata or some other attribute that is not essential to a string object. In object composition, you would have an NSString object as one instance variable of your custom class (typically a subclass of NSObject) and one or more instance variables that store the metadata that you want for the custom object. Then just design your subclass interface to include accessor methods for the embedded string object and the metadata.
If the behavior you want to add supplements that of the existing class, you could write a category onNSString. Keep in mind, however, that this category will be in effect for all instances of NSString that you use, and this might have unintended consequences."


Комментариев нет:

Отправить комментарий