В частности, в Java, но, вероятно, и в других языках: когда было бы полезно иметь две ссылки на один и тот же объект?
Пример:
Dog a = new Dog();
Dob b = a;
Есть ли ситуация, когда это было бы полезно? Почему это предпочтительное решение для использования a
всякий раз, когда вы хотите взаимодействовать с объектом, представленным a
?
object-oriented
object-oriented-design
object
Bassinator
источник
источник
a
иb
всегда ссылаются на одноDog
и то же , то в этом нет никакого смысла. Если они иногда могут, то это весьма полезно.Ответы:
Например, когда вы хотите иметь один и тот же объект в двух отдельных списках :
Другое использование, когда у вас есть один и тот же объект, играющий несколько ролей :
источник
Persona batman = new Persona("Batman"); Persona bruce = new Persona("Bruce Wayne"); Persona currentPersona = batman;
- где у вас есть несколько возможных значений (или список доступных значений) и ссылка на текущее активное / выбранное значение.currentPersona
указывает на один объект или другой, но никогда не на оба. В частности, это может легко быть возможно , чтоcurrentPersona
никогда и не установленbruce
, в этом случае это, конечно , не является ссылкой на два объекта. Я бы сказал, что в моем примере обаbatman
иcurrentPersona
являются ссылками на один и тот же экземпляр, но в программе используются разные смысловые значения.Это на самом деле удивительно глубокий вопрос! Опыт современного C ++ (и языков, основанных на современном C ++, таких как Rust) показывает, что очень часто вы этого не хотите! Для большинства данных вам нужна единственная или уникальная («владеющая») ссылка. Эта идея также является одной из основных причин систем линейного типа .
Однако даже в этом случае вам обычно нужны кратковременные «заимствованные» ссылки, которые используются для краткого доступа к памяти, но не длятся в течение значительной части времени, в течение которого существуют данные. Чаще всего, когда вы передаете объект в качестве аргумента другой функции (параметры тоже являются переменными!):
Менее распространенный случай, когда вы используете один из двух объектов в зависимости от условия, делая по существу одно и то же независимо от того, какой вы выберете:
Возвращаясь к более распространенному использованию, но оставляя позади локальные переменные, мы обратимся к полям: например, виджеты в платформах GUI часто имеют родительские виджеты, поэтому ваш большой фрейм, содержащий десять кнопок, будет иметь по меньшей мере десять ссылок, указывающих на него (плюс еще некоторые от его родителя и, возможно, от слушателей событий и так далее). Любой вид графа объектов и некоторые виды деревьев объектов (с родительскими / родными ссылками) имеют несколько объектов, ссылающихся на один и тот же объект. И практически каждый набор данных на самом деле является графиком ;-)
источник
Временные переменные: рассмотрим следующий псевдокод.
Переменные
max
иcandidate
могут указывать на один и тот же объект, но назначение переменных изменяется с использованием разных правил и в разное время.источник
Чтобы дополнить другие ответы, вы также можете по-разному обходить структуру данных, начиная с одного и того же места. Например, если у вас есть
BinaryTree a = new BinaryTree(...); BinaryTree b = a
, вы можете пройти по крайнему левому пути дерева с помощьюa
и к крайнему правому путиb
, используя что-то вроде:Прошло много времени с тех пор, как я написал Java, поэтому этот код может быть неправильным или осмысленным. Воспринимайте это как псевдокод.
источник
Этот метод удобен, когда у вас есть несколько объектов, которые все обращаются к другому объекту, который можно использовать бесконтактно.
Например, если у вас есть интерфейс с вкладками, у вас могут быть Tab1, Tab2 и Tab3. Вы также можете захотеть использовать общую переменную независимо от того, на какой вкладке находится пользователь, чтобы упростить ваш код и избавиться от необходимости на лету выяснять, на какой вкладке находится ваш пользователь.
Затем в каждой из пронумерованных вкладок на Click вы можете изменить CurrentTab для ссылки на эту вкладку.
Теперь в вашем коде вы можете безнаказанно вызывать «CurrentTab» без необходимости знать, на какой вкладке вы находитесь. Вы также можете обновить свойства CurrentTab, и они автоматически перетекут на указанную вкладку.
источник
Существует множество сценариев, в которых
b
должна быть ссылка на неизвестное "a
", чтобы быть полезным. Особенно:b
указывает во время компиляции.Например:
параметры
t
является ссылкой на переменную из внешней области видимости.Возвращаемые значения и другие условные значения
biggerThing
иz
каждая ссылка на илиa
илиb
. Мы не знаем, что во время компиляции.Лямбды и их возвращаемые значения
x
является параметром (пример 1 выше) иt
является возвращаемым значением (пример 2 выше)Коллекции
index["some name"]
в значительной степени более сложный видb
. Это псевдоним объекта, который был создан и добавлен в коллекцию.Loops
t
является ссылкой на элемент, возвращенный (пример 2) итератором (предыдущий пример).источник
Это важный момент, но ИМХО стоит понять.
Все ОО-языки всегда делают копии ссылок и никогда не копируют объект «невидимо». Было бы намного сложнее писать программы, если бы ОО-языки работали как-то иначе. Например, функции и методы никогда не смогут обновить объект. Java и большинство ОО-языков было бы практически невозможно использовать без значительной дополнительной сложности.
Предполагается, что объект в программе имеет некоторый смысл. Например, оно представляет собой нечто конкретное в реальном физическом мире. Обычно имеет смысл иметь много ссылок на одну и ту же вещь. Например, мой домашний адрес может быть предоставлен многим людям и организациям, и этот адрес всегда относится к одному и тому же физическому местоположению. Итак, первое, что объекты часто представляют что-то конкретное, реальное или конкретное; и поэтому возможность иметь много ссылок на одну и ту же вещь чрезвычайно полезна. Иначе было бы сложнее писать программы.
Каждый раз, когда вы передаете
a
в качестве аргумента / параметра другую функцию, например, вызываетеfoo(Dog aDoggy);
или применяете метод
a
, базовый программный код создает копию ссылки, чтобы создать вторую ссылку на тот же объект.Кроме того, если код со скопированной ссылкой находится в другом потоке, то оба могут использоваться одновременно для доступа к одному и тому же объекту.
Поэтому в большинстве полезных программ будет несколько ссылок на один и тот же объект, потому что это семантика большинства языков программирования ОО.
Теперь, если мы подумаем об этом, поскольку передача по ссылке является единственным механизмом, доступным во многих языках OO (C ++ поддерживает оба), мы можем ожидать, что это будет «правильное» поведение по умолчанию .
ИМХО, использование ссылок является правильным по умолчанию по нескольким причинам:
Есть также аргумент эффективности; создание копий целых объектов менее эффективно, чем копирование ссылки. Тем не менее, я думаю, что это не так. Многократные ссылки на один и тот же объект имеют больше смысла и их легче использовать, поскольку они соответствуют семантике реального физического мира.
Так что, ИМХО, обычно имеет смысл иметь несколько ссылок на один и тот же объект. В необычных случаях, когда это не имеет смысла в контексте алгоритма, большинство языков предоставляют возможность создавать «клон» или глубокую копию. Однако это не по умолчанию.
Я думаю, что люди, которые утверждают, что это не должно быть по умолчанию, используют язык, который не обеспечивает автоматическую сборку мусора. Например, старомодный C ++. Проблема в том, что им нужно найти способ собирать «мертвые» объекты, а не возвращать объекты, которые все еще могут потребоваться; наличие нескольких ссылок на один и тот же объект усложняет задачу.
Я думаю, что если в C ++ была достаточно дешевая сборка мусора, так что все объекты, на которые ссылаются, являются сборщиком мусора, то большая часть возражений исчезнет. Все еще будут случаи, когда семантика ссылок не является необходимой. Однако, по моему опыту, люди, которые могут идентифицировать эти ситуации, также в любом случае способны выбрать подходящую семантику.
Я полагаю, что есть некоторые свидетельства того, что большой объем кода в программе на C ++ предназначен для обработки или уменьшения сбора мусора. Однако написание и поддержание такого рода «инфраструктурного» кода увеличивает стоимость; это делается для того, чтобы сделать язык более легким в использовании или более надежным. Так, например, язык Go разработан с упором на исправление некоторых слабых мест C ++, и у него нет другого выбора, кроме сборки мусора.
Это, конечно, не имеет значения в контексте Java. Он также был разработан, чтобы быть простым в использовании, а также сборка мусора. Следовательно, наличие нескольких ссылок является семантикой по умолчанию и относительно безопасно в том смысле, что объекты не возвращаются, пока есть ссылка на них. Конечно, они могут удерживаться структурой данных, потому что программа не приводит в порядок, когда она действительно закончила работу с объектом.
Итак, возвращаясь к вашему вопросу (с небольшим обобщением), когда вы захотите более одной ссылки на один и тот же объект? Практически во всех ситуациях, о которых я могу думать. Они являются семантикой по умолчанию для большинства языков механизма передачи параметров. Я полагаю, что это потому, что семантика по умолчанию для обработки объектов, которая существует в реальном мире, в значительной степени должна быть по ссылке (потому что реальные объекты там).
С любой другой семантикой будет сложнее справиться.
Я полагаю, что «ровер»
dl
должен быть тем, на который влияют,setOwner
или программам трудно писать, понимать, отлаживать или изменять. Я думаю, что большинство программистов были бы озадачены или встревожены в противном случае.позже собака продается:
Этот вид обработки является обычным и нормальным. Так что семантика ссылок - это значение по умолчанию, потому что это обычно имеет смысл.
Резюме: всегда имеет смысл иметь несколько ссылок на один и тот же объект.
источник
Конечно, еще один сценарий, в котором вы могли бы в конечном итоге:
это когда вы поддерживаете код и
b
раньше были другой собакой или другим классом, но теперь обслуживаютсяa
.Как правило, в среднесрочной перспективе вы должны переработать весь код, на который ссылаетесь
a
напрямую, но это может произойти не сразу.источник
Вы захотите этого в любое время, когда у вашей программы есть шанс поместить объект в память более чем в одном месте, возможно, потому, что его используют разные компоненты.
Карты удостоверений предоставляют определенное локальное хранилище сущностей, поэтому мы можем избежать двух или более отдельных представлений. Когда мы представляем один и тот же объект дважды, наш клиент рискует вызвать проблему параллелизма, если одна ссылка на объект сохраняет свои изменения состояния раньше, чем другой другой экземпляр. Идея в том, что мы хотим убедиться, что наш клиент всегда имеет точную ссылку на нашу сущность / объект.
источник
Я использовал это при написании решателя судоку. Когда я знаю номер ячейки при обработке строк, я хочу, чтобы содержащий столбец также знал номер этой ячейки при обработке столбцов. Таким образом, и столбцы, и строки являются массивами объектов Cell, которые перекрываются. Точно так же, как показал принятый ответ.
источник
В веб-приложениях Object Relational Mappers могут использовать отложенную загрузку, так что все ссылки на один и тот же объект базы данных (по крайней мере, в одном потоке) указывают на одну и ту же вещь.
Например, если у вас было две таблицы:
Собаки:
Владельцы:
Существует несколько подходов, которые ваш ORM может использовать, если выполняются следующие вызовы:
В наивной стратегии все обращения к моделям и связанные ссылки извлекают отдельные объекты.
Dog.find()
,Owner.find()
,owner.dogs
, Иdog.owner
результат в базе данных попал в первый раз, после чего они будут сохранены в память. И так:Без ссылки у вас будет больше выборок, больше памяти и вы сможете перезаписать более ранние обновления.
Предположим, что ваш ORM знает, что все ссылки на строку 1 таблицы собак должны указывать на одно и то же. Потом:
Другими словами, использование ссылок помогает кодифицировать принцип единой точки правды (по крайней мере, внутри этого потока), являющейся строкой в базе данных.
источник