Динамическая типизация

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск
Типизация данных

Типобезопасность
Вывод типов
Статическая типизация
Динамическая типизация
Сильная и слабая типизация
Зависимые типы
Утиная типизация

Динами́ческая типиза́ция — приём, широко используемый в языках программирования и языках спецификации, при котором переменная связывается с типом в момент присваивания значения, а не в момент объявления переменной. Таким образом, в различных участках программы одна и та же переменная может принимать значения разных типов. Примеры языков с динамической типизацией — Smalltalk, Python, Objective-C, Ruby, PHP, Perl, JavaScript, Lisp, xBase, Erlang.

Противоположный приём — статическая типизация.

В некоторых языках со слабой динамической типизацией стоит проблема сравнения величин, так, например, PHP имеет операции сравнения «==», «!=» и «===», «!==», где вторая пара операций сравнивает и значения, и типы переменных. Операция «===» даёт true только при полном совпадении, в отличие от «==», который считает верным такое выражение: (1=="1"). Стоит отметить, что это проблема не динамической типизации в целом, а конкретных языков программирования.

Преимущества[править | править вики-текст]

  • Упрощается написание несложных программ, например, скриптов.
  • Облегчается работа прикладного программиста с СУБД, которые принципиально возвращают информацию в «динамически типизированном» виде. Поэтому динамические языки ценны, например, для программирования веб-служб.
  • Иногда требуется работать с данными переменного типа. Например, функция поиска подстроки возвращает позицию найденного символа (число) или маркер «не найдено». В PHP этот маркер — булевое false. В языках со статической типизацией это особая константа (0 в Паскале, std::string::npos в C++).

Недостатки[править | править вики-текст]

  • Статическая типизация позволяет уже при компиляции заметить простые ошибки «по недосмотру». Для динамической типизации требуется как минимум выполнить данный участок кода.
  • В объектно-ориентированных языках не действует, либо действует с ограничениями, автодополнение: трудно или невозможно понять, к какому типу относится переменная, и вывести набор её полей и методов. [источник?]
  • Развитая статическая система типов (такая как Хиндли-Милнер) играет значительную роль в самодокументировании программы[1]; динамическая типизация по определению не проявляет этого свойства, что затрудняет разработку структурно сложных программ.
  • Снижение производительности из-за трат процессорного времени на динамическую проверку типа, и излишние расходы памяти на переменные, которые могут хранить «что угодно». К тому же большинство языков с динамической типизацией интерпретируемые, а не компилируемые.

Примеры[править | править вики-текст]

PHP[править | править вики-текст]

$res  = "string1"; echo $res."\n";  // выводит "string1" - переменная имеет строковый тип.
$res  = 1;         echo $res."\n";  // выводит "1" - переменная преобразуется в целочисленный тип.
$res += 2;         echo $res."\n";  // выводит "3" - результат операции: целочисленная переменная.
$res .= "string2"; echo $res."\n";  // выводит "3string2" - переменная преобразуется в строковый тип и выполняется конкатенация.

Python[править | править вики-текст]

var = "string1"
print(var) # Выведет "string1"
var = 1
print(var) # Выведет "1"
var += 2
print(var) # Выведет "3"

# Однако, такой ход в Python невозможен:
var += "string2" # Порождается исключение TypeError: unsupported operand type(s) for +=: 'int' and 'str'

var = str(var)   # и потребуется явное преобразование типов
var += "string2" # теперь ОК
print(var) # Выведет "3string2"

JavaScript[править | править вики-текст]

var res = "string1"; alert(res);  // выводит 'string1'
res = 1;             alert(res);  // выводит 1
res += 2;            alert(res);  // выводит 3
res += 'string2';    alert(res);  // выводит '3string2'

Object Pascal[править | править вики-текст]

program Project2;
{$APPTYPE CONSOLE}
Uses   SysUtils;
Var    V1, V2: Variant;
begin
    V1  := 'string1';  WriteLn(V1);           // выводит "string1"  
    V2  := 1;          WriteLn(V2);           // выводит "1"        
    Inc(V2,2);         WriteLn(V2);           // выводит "3"        
                       WriteLn(V2,'string2'); // выводит "3string2" 
end.

Object Pascal: Другие способы использования динамической типизации

procedure TForm1.Myproc(Obj: TObject);
begin
If (Obj is TButton)
   then (Obj as TButton).Click;
end;
function Something (A: array of const)
begin
  // ...
end;
{Вызов: } Something ( [5,'Hello',3.14159, True, TForm] );

procedure TForm1.DisplayValue(const AValue: TValue);
begin
Memo1.Lines.Append(AValue.ToString);
end;

procedure TForm1.btn1Click(Sender: TObject);
var
list: TStrings;
begin
 list := TStringList.Create();
 list.Text := 'Foo';
 try
   DisplayValue(list);
   DisplayValue(list.Count);
   DisplayValue(list.Capacity * 8.964);
   DisplayValue(list is TStringList);
   DisplayValue(list.Text);
 finally
   list.Free;
 end;
end;
{Вывод:
(TStringList @ 0166E460)
1
35,856
True
Foo
}

Примечания[править | править вики-текст]

См. также[править | править вики-текст]

Ссылки[править | править вики-текст]