Даункастинг
Эта статья включает список общих ссылок , но в ней отсутствуют достаточные соответствующие встроенные цитаты . ( Август 2008 г. ) |
В на основе классов программировании понижающее приведение или уточнение типа — это приведение или ссылки на базовый родительский класс к более ограниченной ссылке на производный класс . [1] Это допустимо только в том случае, если объект уже является экземпляром производного класса, и поэтому такое преобразование по своей сути ошибочно.
Во многих средах интроспекция типов может использоваться для получения типа экземпляра объекта во время выполнения, а затем использовать этот результат для явной оценки совместимости его типа с другим типом. Возможные результаты сравнения полиморфных типов — помимо того, что они эквивалентны (идентичны) или не связаны (несовместимы) — включают два дополнительных случая: а именно, когда первый тип является производным от второго, а затем то же самое, но заменено наоборот. (см.: Подтипирование § Подстановка ).
С помощью этой информации программа может перед выполнением такой операции, как сохранение объекта в типизированной переменной, проверить, является ли эта операция типобезопасной или приведет ли она к ошибке. Если тип экземпляра среды выполнения является производным (дочерним) от типа целевой переменной (следовательно, родительской), возможно понижающее приведение.
Некоторые языки, такие как OCaml , запрещают понижающее приведение. [2]
Примеры
[ редактировать ]Ява
[ редактировать ]public class Fruit{} // parent class
public class Apple extends Fruit{} // child class
public static void main(String[] args) {
// The following is an implicit upcast:
Fruit parent = new Apple();
// The following is a downcast. Here, it works since the variable `parent` is
// holding an instance of Apple:
Apple child = (Apple)parent;
}
С++
[ редактировать ]// Parent class:
class Fruit {
public:
// Must be polymorphic to use runtime-checked dynamic-cast.
virtual ~Fruit() = default;
};
// Child class:
class Apple : public Fruit {};
int main(int argc, const char** argv) {
// The following is an implicit upcast:
Fruit* parent = new Apple();
// The following is a downcast. Here, it works since the variable `parent` is
// holding an instance of Apple:
Apple* child = dynamic_cast<Apple*>(parent);
}
Использование
[ редактировать ]Понижающее приведение полезно, когда тип значения, на которое ссылается родительская переменная, известен и часто используется при передаче значения в качестве параметра. В приведенном ниже примере метод objectToString принимает параметр Object, который предположительно имеет тип String.
public static String objectToString(Object myObject) {
// This will only work when the myObject currently holding value is string.
return (String)myObject;
}
public static void main(String[] args) {
// This will work since we passed in String, so myObject has value of String.
String result = objectToString("My String");
Object iFail = new Object();
// This will fail since we passed in Object which does not have value of String.
result = objectToString(iFail);
}
В этом подходе понижающее приведение не позволяет компилятору обнаружить возможную ошибку и вместо этого вызывает ошибку во время выполнения. Преобразование myObject в String («(String)myObject») было невозможно во время компиляции, поскольку бывают случаи, когда myObject имеет тип String, поэтому только во время выполнения мы можем выяснить, является ли переданный параметр логическим. Хотя мы также могли бы преобразовать myObject в строку времени компиляции, используя универсальный метод java.lang.Object.toString(), это могло бы привести к вызову реализации toString() по умолчанию, где это было бы бесполезно или небезопасно, а обработка исключений не могла бы предотвратить это. .
В C++ проверка типов во время выполнения реализуется через динамический_cast . Понижение типа во время компиляции реализуется static_cast , но эта операция не выполняет проверку типа. Если его использовать неправильно, это может привести к неопределенному поведению.
Соображения
[ редактировать ]Популярный пример плохо продуманной конструкции — контейнеры верхних типов , [ нужна ссылка ] например, контейнеры Java до появления дженериков Java , что требует понижения уровня содержащихся объектов, чтобы их можно было использовать снова.
См. также
[ редактировать ]Ссылки
[ редактировать ]- ^ ТайлерMSFT (3 августа 2021 г.). «Как использовать Safe_cast в C++/CLI» . Learn.microsoft.com . Проверено 1 декабря 2023 г.
- ^ Вуийон, Жером; Реми, Дидье; Гарриг, Жак (12 сентября 2013 г.). «Объекты в OCaml» . Система OCaml, версия 4.01: Документация и руководство пользователя .
Внешние ссылки
[ редактировать ]- Даункастинг — это кодовый запах Джереми Д. Миллера
- Унылая трагедия Джимми Богарда
- Предпочитайте полиморфизм экземпляру и приведению Билла Веннерса
- Понижающее приведение в C#, Скотт Лайсл
- Несколько методов даункастинга
- Повышение, понижение от Sinipull