Рубрики
Без рубрики

Сравнение значений и ссылок на различных языках программирования

В этом посте мы увидим, как различные языки решили проблему сравнения значений и ссылок. O то же самое, чтобы определить, содержат ли две переменные один и тот же объект или содержат два разных, но идентичных объекта. Обычно сравнение ссылок называется сравнением по ссылке и при сравнении, если два объекта равны (но не обязательно одинаковы) это называется сравнением по значению. С тегами java, javascript, csharp, испанский.

Автор//Эдуард Фома в campusMVP

В этом посте мы увидим, как различные языки решили проблему сравнения значений и ссылок. O то же самое, чтобы определить, содержат ли две переменные один и тот же объект или содержат два разных, но идентичных объекта. Обычно сравнение ссылок называется сравнением по ссылке и при сравнении, если два объекта равны (но не обязательно одинаковы) это называется сравнением по значению.

Точно так же мы говорим, что тип имеет семантику значения если мы заботимся только о его ценности, но не о его личности. Если семантика значения полностью применяется, она обеспечивает неизменность объекта: любое изменение объекта генерирует копию//такого объекта, как оператор присваивания.

Это, казалось бы, простая тема, но которая, как и почти все в этом захватывающем мире развития, дает больше, чем кажется на первый взгляд. Начнем с Java…

Ява

Java-это язык, который наиболее упрощает этот вопрос. Таким образом, оператор равенства ( = = ) сравнивает ссылки. То есть, учитывая следующий код:

MyClass m1 = new MyClass();
MyClass m2 = new MyClass();
boolean eq = m1 == m2;

Переменная eq стоит//false//, поскольку m1 и m2 содержат два разных объекта. Независимо от того, идентичны ли они, важно то, что это два разных объекта. На самом деле одна из наиболее распространенных ошибок в Java-это сравнение строк с помощью оператора сравнения:

boolean areEqual = "Hola" == "Hola";

В Java строки являются объектом, и каждый раз, когда мы используем литерал, создается новый объект, поэтому areEqual будет стоить false : у нас есть две одинаковые строки, но они все еще два объекта. Хорошо, прежде чем вы бежите в Eclipse, чтобы скопировать этот код и увидеть, что areEqual//true |/(вместо//false |/) я скажу вам, что это потому, что в некоторые случаи компилятор Java может сделать оптимизацию и увидеть, что на самом деле обе строки одинаковы и, таким образом, просто создать объект. Но это оптимизация компилятора, а не языка. В других контекстах, когда компилятор не может обнаружить это (например, читая эту строку из файла), то areEqual будет стоить//false .

Java включает в себя механизм сравнения по значению: метод equals, определенный в классе Object(базовый класс всех классов в Java). Такой метод должен быть переопределен во всех тех классах, которые должны предоставлять семантику сравнения по значению. Таким образом, правильный механизм для сравнения строк в Java будет:

boolean areEqual = oneString.equals(anotherString);

Где oneString и anotherString являются переменными типа String.

En Java los tipos простые (int, логическое, двойное,…) они не являются классами, и в этом случае они всегда сравниваются по значению при использовании оператора сравнения. Простые типы в Java имеет семантику значений.

C#

В C#все становится намного интереснее. C# часть той же идеи Java: оператор сравнения (==) сравнивает по ссылке, тогда как для сравнения по значению существует метод Equals, определенный в классе Object (суперкласс всех классов в C#). Отличий от Java принципиально три.

Сначала C# (и .NET в целом) позволяют определять типы с семантикой значений. В C# слово struct используется для определения типа, семантика которого по значению. Только одна деталь: structs в C# не являются неизменяемыми (хотя мой личный совет заключается в том, что если вы когда-либо создадите их, сделайте их неизменяемыми ). Когда в C# вы создаете struct, вы должны предоставить реализацию оператора ==. Если вы этого не сделаете, вы не сможете использовать этот оператор для сравнения!

Например. мы могли бы определить struct, используя следующий код:

struct Foo
{
    public int Bar { get; set; }
    public static bool operator !=(Foo one, Foo other)
    {
        return !(one == other);
    }
    public static bool operator ==(Foo one, Foo other)
    {
        return one.Bar == other.Bar;
    }
}

Примечание: Если мы переопределим оператор равенства, C# также заставляет нас переопределить оператор без равенства (!=).

Второй C# позволяет переопределить оператор сравнения (==). Это означает, что даже если у нас есть класс, мы можем реализовать семантику сравнения по значению, переопределив ==. Переопределение оператора вы должны сделать это в том случае, если вы создаете класс, объекты которого неизменяемы.

И, наконец, в C# “простые типы” На самом деле не существуют-это все объекты. Все” простые типы ” C# (int, bool, float) являются псевдонимами для типов .NET Рамки (стр.ej. int-это псевдоним Int32). Такие типы реализованы с семантикой значений (они являются structs).

Поэтому обратите внимание, что в C# возможности умножаются. Обычно у вас есть класс, который при сравнении с использованием сравнения по ссылке и при использовании Equals(если он переопределен) сравнивается по значению. Но у нас может быть класс, который сравнивается со значением при использовании == (не идя дальше String-это класс и не struct и имеет оператор).

Так, например. когда у вас есть следующий код:

var eq = "Hola" == "Hola"

Вы сравниваете два объекта String, поэтому это должно априори//возвращать//false//. Pero la clase Stringtiene el operador para, чтобы сравнить доблесть, доблесть и справедливость правда . Со своей стороны, следующий код:

var eq = 1 == 1;

Вы сравниваете два объекта Int32. Int32 является struct, так что оператор по значению (при условии, что он хорошо реализован!). Так что eq снова стоит//true//. Наконец, в этом коде:

var f1 = new Foo() {Bar=10};
var f2 = new Foo() {Bar=10};
var eq = f1 == f2;

Мало что можно сказать. Если Foo является классом и он не имеет оператора eq будет стоить false|/, так как он сравнивается по ссылке. С другой стороны, если Foo является struct , который мы определили раньше, то eqдолжно вернуть true , так как тогда оператор по значению.

JavaScript

В JavaScript все намного проще: нет сравнения по значению, это всегда по ссылке, за исключением простых типов (логические значения, числа и строки). В остальных случаях оператор, если две ссылки указывают на один и тот же объект.

Таким образом, учитывая следующий код:

var a={};
var b={}
var eq = a==b;

В конце eq будет стоить//false.

Если мы хотим сравнения по значению, мы должны реализовать их вручную. На самом деле в C# и Java мы должны сделать это одинаково (мы должны переопределить Равно o equals) но, по крайней мере, оба языка дают нам точку “где разместить” код для сравнения по значению (хотя это имеет побочный эффект, что любой объект имеет метод Equals или equals даже если они не переопределены и, следовательно, сравнение по значению неверно.)

Но JavaScript вводит новый дополнительный оператор сравнения. Тройной равный (===). Такой оператор идентичен двойному равному, но с одним фундаментальным отличием: он не выполняет принуждение типов. Принуждение типов-это функция автоматического преобразования данных определенного типа в данные другого типа. Несмотря на то, что многие люди верят, принуждение типов не имеет ничего общего с тем, что язык является динамическим (например, JavaScript) или статическим. На самом деле C# является статическим, строго типизированным языком и поддерживает принуждение типов. Проблема в JavaScript заключается в том, что принуждения очень широки, поэтому сравнения иногда проводятся с, казалось бы, неправильные данные (с точки зрения разработчика, конечно).

Таким образом, код:

1 == "1"

Возвращает//true|/, так как принуждение типов “1” преобразуется в число. Есть строка, которая преобразуется в число, потому что тип слева является числом (принуждение всегда применяется к типу справа к парню слева). С другой стороны, следующий код:

1 + 1 == 1+"1"

Возвращает false . Потому что оператор sum преобразует все аргументы в строку, если таковые имеются. Таким образом, 1+ ” 1 “эквивалентно”1″+” 1″, что стоит”11″. Затем перед сравнением строка ” 11 ” преобразуется в число (11) и сравнивается с 2 (результат 1+1 слева).

Чтобы избежать этих иногда “нелогичных” результатов, есть оператор тройного равенства. На самом деле вы должны всегда использовать JavaScript, если у вас нет четкой причины этого не делать. Этот оператор сравнивает значения, но отключает принуждение типов. Так:

1==="1"

Возвращает false, так как типы (числовые с одной стороны и строки с другой другие не совпадают).

Быстрый

¿ Что Swift должен добавить к теме сравнений? Ну, на самом деле ничего, что мы еще не виделись. Но его синтаксис может немного смутить тех, кто исходит из … любого другого языка.

Причина в том, что Swift имеет, как и JavaScript, два оператора сравнения: двойной равный (==) и тройной равный (===). Но его использование не имеет ничего общего с использованием JavaScript. Просто:

  1. Оператор сравнение по значению (эквивалентно методу Равно de C# o равно de Java).
  2. Оператор сравнение по ссылке (эквивалентно оператору Java и обычно к оператору C#).

Когда мы создаем собственный класс в Swift, мы должны предоставить реализацию оператора, мы хотим, чтобы его объекты могли сравниваться по значению-это аналогично переопределению метода   Равно en C#:

@infix func == (left: Vector2D, right: Vector2D) -> Bool {
    return (left.x == right.x) && (left.y == right.y)
}
@infix func != (left: Vector2D, right: Vector2D) -> Bool {
    return !(left == right)
}

Однако Swift, как и C#, различает типы по ссылке (классы) и типы по значению (structs). Когда переменная типа struct назначается другой, целочисленный объект копируется, поэтому у нас есть два разных объекта (как в C#). В этом случае оператор возвращает false при сравнении двух переменных типа struct, даже если они содержат два одинаковых объекта.

И с Swift мы заканчиваем этот тур о том, как различные языки реализовали что-то априори так просто, как “сравнение двух переменных”:)

Оригинальный пост: https://www.campusmvp.es/recursos/post/Comparando-valores-y-referencias-en-varios-lenguajes-de-programacion.aspx

Оригинал: “https://dev.to/campusmvp/comparando-valores-y-referencias-en-varios-lenguajes-de-programacin-1n7n”