В C # (и некоторых других языках) каждый объект имеет два типа: статический тип и динамический тип .Статический тип объекта (в вашем примере: Animal
) определяется во время компиляции, а динамический тип (в вашем примере: Dog
) определяется во время выполнения.Рассмотрим следующее:
Animal animal;
if (userInput)
animal = new Wolf();
else
animal = new Dog();
Компилятор не может определить, какой динамический тип животного будет иметь.Он определяется только во время выполнения
Динамический тип всегда должен быть как минимум статическим типом объекта.Это недопустимо и приведет к ошибкам компиляции:
Dog d = new Animal(); // X
Animal a = new Car(); // X (assuming car does not inherit from animal)
Почему это полезно?В отличие от языков с динамической типизацией (где есть только динамический тип и нет статического), компилятор может проверять ошибки ввода.Это хорошо, потому что мы хотим отлавливать ошибки как можно раньше.
В моем примере компилятор не знает, является ли animal
Wolf
или Dog
, но оба являются производными от Animal
, так что это может бытьуверен, что любая операция Aminal
может быть выполнена на animal
.Попытка выполнить другие операции приведет к ошибке компиляции.
С другой стороны, мы можем добиться мощных возможностей, которые невозможны без системы «двойного типа».Предположим, что Aminal
имеет операцию eat
.Оба Dog
и Wolf
также реализуют питание, каждое по-своему.Давайте рассмотрим следующий пример:
Animal a = new Animal();
Animal d = new Dog();
a.eat(); // Animal's eat
d.eat(); // Dog's eat
Здесь мы видим, что, хотя статический тип d
равен Animal
, фактическая версия вызываемой функции определяется динамическим типом.Это позволяет нам делать то, что называется полиморфизм .Я покажу вам пример:
Animal zoo[100]; // each animal in the zoo array is a static type Animal
zoo[0] = new Dog(); // first element of the array is of dynamic type Dog
zoo[1] = new Cat();
zoo[2] = new Rabbit();
...
// Now the array holds different types of animals. We want to feed them all, but each one in it's own way.
foreach(Animal a in zoo)
a.eat();
Подведем итог:
- Статический тип, известный во время компиляции.Используется для определения допустимости операции над объектом.
- Динамический тип известен только во время выполнения.Используется для выбора операции для выполнения.Для этого есть другой термин: динамическая отправка