Тип объекта (объектно-ориентированное программирование) - Object type (object-oriented programming)
В информатике , тип объекта ( так называемый объект оберточной ) является тип данных , который используется в объектно-ориентированном программировании , чтобы обернуть тип не-объект , чтобы сделать его похожим на динамический объект .
Некоторые объектно-ориентированные языки программирования делают различие между ссылочными типами и типами значений , часто называемыми объектами и не-объектами на платформах, где не существуют сложные типы значений, по таким причинам, как эффективность времени выполнения и синтаксические или семантические проблемы. Например, в Java есть примитивные классы-оболочки, соответствующие каждому примитивному типу : Integer
and int
, Character
and char
, Float
and и 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 + b
a
b
Integer
Integer
c
Objects.equals
Другой пример: J2SE 5.0 позволяет программисту обрабатывать коллекцию (например, a LinkedList
) так, как если бы она содержала int
значения вместо Integer
объектов. Это не противоречит сказанному выше: коллекция по-прежнему содержит только ссылки на динамические объекты и не может перечислять примитивные типы. Это не может быть , но вместо этого он должен быть . Однако компилятор автоматически преобразует код так, что список будет «незаметно» получать объекты, в то время как исходный код упоминает только примитивные значения. Например, теперь программист может писать и думать так, как если бы они были добавлены в список; но компилятор фактически преобразовал строку в .
LinkedList<int>
LinkedList<Integer>
list.add(3)
int
3
list.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.