Почему можно определить переменную с типом суперкласса, но назначить ей объект подкласса? - PullRequest
1 голос
/ 08 мая 2009

Это все еще не совсем ясно для меня. Пример:

NSArray * arr = [[NSMutableArray alloc] init];

Я имею в виду ... да, это работает. НО: Почему я могу сказать компилятору: «Эй, моя переменная - это просто NSArray, вам просто нужно зарезервировать пространство, чтобы он туда поместился», а затем, на самом деле, в это место приходит большой, толстый NSMutableArray, который имеет путь больше методов, больше переменных экземпляра, и просто нужно больше места. Я имею в виду ... как это возможно?

Я бы понял другой путь: большой толстый NSMutableArray на левой стороне, и маленький NSArray и правый. Насколько я понимаю, суперкласс всегда меньше, менее сложен, чем подкласс. Подкласс может переопределить некоторые вещи, но он также может добавить некоторые вещи. Верно?

Представьте, что вы покупаете гараж, потому что ваша жена сказала вам по телефону, что купила что-то, что может водить. Тогда это не просто маленькая машина, как вы думали. Она купила большой грузовик. И это там не вписывается.

Так, как я должен думать об этом, чтобы получить это в моей голове? ;)

Это относится к вики сообщества, на случай, если другие тоже будут сбиты с толку.

Ответы [ 7 ]

5 голосов
/ 08 мая 2009

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

В Objective-C, как и в Java, переменная содержит только ссылку на объект - участие компилятора на этом заканчивается. Сам объект находится в области памяти, известной как куча, которая поддерживается средой выполнения.

5 голосов
/ 08 мая 2009

Размер объекта не имеет к этому никакого отношения, поскольку при присваивании присваивается только ссылка (его можно рассматривать как адрес памяти). Размер ссылки фиксированный и не зависит от размера объекта.

2 голосов
/ 08 мая 2009

Мне кажется, вы озадачены двумя аспектами этого. Один из них связан с распределением пространства, на которое был адресован ряд других ответов. Подводя итог, можно сказать, что объявление ссылки в объектно-ориентированной системе не выделяет пространство для хранения объекта этого типа, оно просто выделяет пространство для хранения указателя.

Другая проблема, которую вы, похоже, смущаете, - это то, что на самом деле означает типизация в объектно-ориентированной системе.

Я бы понял по-другому: Большой жирный NSMutableArray на левой стороне, и крошечный NSArray и право.

Думайте о любом классе как о двух отдельных вещах: интерфейсе, который представляет собой набор методов и членов, которые он предоставляет, и реализации, которая определяет, какой доступ к этим методам и члену будет фактически выполняться.

Когда вы объявляете ссылку на NSArray, это означает, что ссылка будет указывать на объекты, которые поддерживают тот же интерфейс, что и NSArray. Поскольку NSMutableArray является подклассом NSArray, экземпляры NSMutableArray всегда будут поддерживать интерфейс NSArray. Поэтому назначение безопасно.

И наоборот, если вы объявляете ссылку на NSMutableArray, она должна указывать на объекты, которые поддерживают интерфейс подкласса. Следовательно, вы не можете назначить указатель на экземпляр NSArray для этой переменной, потому что NSArray не поддерживает полный интерфейс NSMutableArray. (В слабо типизированной системе возможно, что вы можете выполнить присваивание, но затем получите ошибку времени выполнения, если попытаетесь вызвать метод, который существует в интерфейсе, но не в экземпляре объекта. Я не знаю, насколько сильно типизирован Objective С есть.)

2 голосов
/ 08 мая 2009

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

Чтобы исправить свою аналогию, вы сказали кому-то построить гараж, достаточно большой для машины вашей жены. И все, что вы делаете, это указывает, где находится этот гараж. Вы можете указывать на большой гараж или маленький гараж, для вас это не имеет значения, поскольку вы указываете только своей жене, где находится гараж, а кто-то другой позаботился о том, чтобы гараж был достаточно большим.

1 голос
/ 08 мая 2009

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

Чтобы использовать вашу аналогию, представьте, что у вас есть несколько гаражей, где у вашей жены есть свои машины. Очевидно, что автомобили имеют разные размеры, но это не мешает вам иметь список с номером каждой машины (у вашей жены первая машина была помечена как 1, следующие 2) и где этот автомобиль в настоящее время припаркован (у вашей жены так много автомобили, которые вы должны держать на своих парковках с номерами). Автомобили имеют разные размеры и разные модели, но вы все равно можете записать их все в список, и они все еще являются автомобилями, так что у них есть что-то общее (вы можете, например, водить их, каждая получает столько и много миль на галлон).

Одним из преимуществ объектно-ориентированного программирования является то, что подклассы могут использоваться вместо их суперкласса.

1 голос
/ 08 мая 2009

Вы забываете о системе типов. NSArray - это каркасный класс, а не языковой примитив. Есть информация, которая поддерживается системой времени выполнения.

1 голос
/ 08 мая 2009

В более строго типизированных языках вполне нормально хранить указатель на объект подкласса в переменной, которая была объявлена ​​как указатель на базовый класс. Однако вы не можете получить доступ ни к одному из методов или переменных-членов подкласса.

Objective-C не так сильно типизирован, особенно w.r.t. вызовы сообщений, где (AFAICR) нет проверки типов, и вы получаете ошибку во время выполнения или не выполняете операцию, если запрошенное сообщение не может быть обработано.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...