Тип объекта (объектно-ориентированное программирование) - Object type (object-oriented programming)

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

Некоторые объектно-ориентированные языки программирования делают различие между ссылочными типами и типами значений , часто называемыми объектами и не-объектами на платформах, где не существуют сложные типы значений, по таким причинам, как эффективность времени выполнения и синтаксические или семантические проблемы. Например, в Java есть примитивные классы-оболочки, соответствующие каждому примитивному типу : Integerand int, Characterand char, Floatand и floatт. Д. Такие языки, как C ++, имеют мало или совсем не имеют понятия ссылочного типа ; таким образом, использование типа объекта не представляет особого интереса.

Заниматься боксом

Упаковка, также известная как упаковка, - это процесс помещения примитивного типа в объект, чтобы этот примитив можно было использовать в качестве ссылочного объекта. Например, в Java a LinkedListможет изменять свой размер, но массив должен иметь фиксированный размер. Кто-то может пожелать иметь LinkedListиз int, но LinkedListкласс перечисляет только ссылки на динамические объекты - он не может перечислять примитивные типы, которые являются типами значений.

Чтобы обойти это, intможно поместить в блоки Integer, которые являются динамическими объектами, а затем добавить в LinkedListиз Integer. (Используя универсальные параметризованные типы, представленные в J2SE 5.0, этот тип представлен как .) С другой стороны, C # не имеет примитивных классов-оболочек, но позволяет упаковывать любой тип значения, возвращая универсальную ссылку. В Objective-C к любому примитивному значению может быть добавлен префикс a, чтобы сделать из него значение (например, или ). Это позволяет добавлять их в любую из стандартных коллекций, например в . LinkedList<Integer>Object@NSNumber@123@(123)NSArray

Упакованный объект всегда является копией объекта значения и обычно неизменяем . Распаковка объекта также возвращает копию сохраненного значения. Повторная упаковка и распаковка объектов может иметь серьезное влияние на производительность, потому что упаковка динамически выделяет новые объекты, а распаковка (если упакованное значение больше не используется) делает их пригодными для сборки мусора . Однако современные сборщики мусора, такие как сборщик мусора Java HotSpot по умолчанию, могут более эффективно собирать недолговечные объекты, поэтому, если объекты в штучной упаковке недолговечны, влияние на производительность может быть не таким уж плохим.

В некоторых языках существует прямая эквивалентность между распакованным примитивным типом и ссылкой на неизменяемый упакованный объектный тип. Фактически, можно заменить все примитивные типы в программе упакованными типами объектов. В то время как присвоение одного примитива другому будет копировать его значение, присвоение из одной ссылки помещенному в коробку объекту другому скопирует значение ссылки для ссылки на тот же объект, что и первая ссылка. Однако это не вызовет никаких проблем, потому что объекты неизменяемы, поэтому семантически нет реальной разницы между двумя ссылками на один и тот же объект или на разные объекты (если вы не смотрите на физическое равенство). Для всех операций, кроме присваивания, таких как арифметика, сравнение и логические операторы, можно распаковать упакованный тип, выполнить операцию и повторно упаковать результат по мере необходимости. Таким образом, можно вообще не хранить примитивные типы.

Автобокс

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

Например, в версиях Java до J2SE 5.0 следующий код не компилировался:

Integer i = new Integer(9);
Integer i = 9; // error in versions prior to 5.0!

Компиляторы до 5.0 не принимали последнюю строку. Integerне являются контрольными объектами, на поверхности не отличается от List, Objectи так далее. Чтобы преобразовать из an intв an Integer, нужно было «вручную» создать экземпляр объекта Integer. Начиная с J2SE 5.0, компилятор примет последнюю строку и автоматически преобразует ее так, чтобы для хранения значения был создан объект Integer 9. Это означает, что, начиная с J2SE 5.0, что-то вроде , where и are сами по себе, теперь будет компилироваться - a и b распакованы, целочисленные значения суммируются, а результат автоматически упаковывается в новое , которое, наконец, сохраняется внутри переменной . Операторы равенства не могут использоваться таким образом, потому что операторы равенства уже определены для ссылочных типов, для равенства ссылок; чтобы проверить равенство значений в упакованном типе, нужно вручную распаковать их и сравнить примитивы или использовать метод. Integer c = a + babIntegerIntegercObjects.equals

Другой пример: J2SE 5.0 позволяет программисту обрабатывать коллекцию (например, a LinkedList) так, как если бы она содержала intзначения вместо Integerобъектов. Это не противоречит сказанному выше: коллекция по-прежнему содержит только ссылки на динамические объекты и не может перечислять примитивные типы. Это не может быть , но вместо этого он должен быть . Однако компилятор автоматически преобразует код так, что список будет «незаметно» получать объекты, в то время как исходный код упоминает только примитивные значения. Например, теперь программист может писать и думать так, как если бы они были добавлены в список; но компилятор фактически преобразовал строку в . LinkedList<int>LinkedList<Integer>list.add(3)int 3list.add(new Integer(3))

Распаковка

Распаковка относится к получению значения, связанного с данным объектом, просто посредством преобразования типа (неявного или явного). Компилятор автоматически предоставляет дополнительный исходный код, который извлекает значение из этого объекта, либо вызывая какой-либо метод для этого объекта, либо другими способами.

Например, в версиях Java до J2SE 5.0 следующий код не компилировался:

Integer k = new Integer(4);
int l = k.intValue(); // always okay
int m = k;            // would have been an error, but okay now

C # не поддерживает автоматическую распаковку в том же смысле, что и Java, потому что в нем нет отдельного набора примитивных типов и типов объектов. Все типы, которые в Java имеют как примитивную, так и объектную версию, автоматически реализуются компилятором C # как либо примитивные (значения), либо как объектные (ссылочные) типы.

На обоих языках автоматическая упаковка не выполняется автоматически, т. Е. Следующий код не компилируется:

C #:

int i = 42;
object o = i;         // box
int j = o;            // unbox (error)
Console.WriteLine(j); // unreachable line, author might have expected output "42"

Ява:

int i = 42;
Object o = i;          // box
int j = o;             // unbox (error)
System.out.println(j); // unreachable line, author might have expected output "42"

Помощники типов

В Modern Object Pascal есть еще один способ выполнения операций с простыми типами, близкий к боксу, называемый помощниками типов в FreePascal или помощниками записи в Delphi и FreePascal в режиме Delphi.
Упомянутые диалекты являются языками компиляции Object Pascal для нативных языков, поэтому в них отсутствуют некоторые функции, которые могут реализовать C # и Java. В частности, вывод типа во время выполнения для строго типизированных переменных.
Но особенность связана с боксом.
Это позволяет программисту использовать такие конструкции, как

{$ifdef fpc}{$mode delphi}{$endif}
uses sysutils;  // this unit contains wraps for the simple types
var
  x:integer=100;
  s:string;
begin
  s:= x.ToString;
  writeln(s);
end.

Рекомендации