В чем разница между "to" и "as" такими префиксами имен методов, как
- составлять список(),
- asList (),
- и т.д...
Когда использовать что при разработке метода?
В чем разница между "to" и "as" такими префиксами имен методов, как
Когда использовать что при разработке метода?
Ответы:
Ожидается, что toXYZ()
функция будет выполнять преобразование и возвращать новый независимый объект (хотя неизменность позволяет оптимизировать, java.lang.String.toString()
просто возвращает объект).
В качестве примера, в C ++ мы std::bitset::to_ulong()
можем легко потерпеть неудачу, и целый ряд to_string()
всех (более или менее) выполняет сложное преобразование и выделение памяти.
С asXYZ()
другой стороны, ожидается, что функция будет возвращать (потенциально другое) представление об источнике, выполняя минимальную работу.
В качестве примера, в C ++ мы имеем, std::as_const()
который просто возвращает постоянную ссылку, и более сложный, std::forward_as_tuple
который также ссылается на свои аргументы по ссылке.
std::to_string(x)
создает новый строковый объект, но std::as_const(x)
создает ссылку (представление) на существующий объект.
Честно говоря, это может быть просто несоответствие имен. Если посмотреть на стандартных библиотечных объектов в Smalltalk, например, все методы , которые делают «сложные преобразования» или «возвращать простые представления в другом типе» начинаются с as
, как asString
, asFloat
, asSeconds
и стандартный метод для преобразования ничего к чему -то еще, as: aClass
.
В Ruby, одни и те же виды методов с префиксом to_
, как и в to_s
, to_a
, to_h
, сокращение string
, array
и hash
соответственно.
Кажется, что ни одна из стандартных библиотек не проводит различий между различными видами преобразований, вероятно, потому, что это следует рассматривать как деталь реализации.
Однако в Java мы видим много путаницы. Как уже упоминалось, есть toString
, asList
и так далее. Я считаю, что это просто несоответствие именования, потому что, если вы попытаетесь определить разные значения для каждого префикса, вы всегда найдете контрпример в другом месте стандартной библиотеки.
Так что в любом случае я бы сказал, что для вас и вашей команды важно выбрать один префикс и использовать его последовательно во всем коде. Последовательность является ключом, поэтому людям не остается удивляться, как и вам.
toString
создает новую строку, полностью отключенную от объекта (и нет другого пути из-за неизменности). То же самое верно, например, для Collection#toArray
, пока Arrays#asList
возвращает представление массива, который связан двунаправленно (изменение массива изменяет список и наоборот). Так что это довольно непротиворечиво, хотя могут быть и исключения. Выбор одного префикса был бы неправильным. Если бы было Arrays#toList
, то я бы ожидал, что это создаст новый список с новым базовым массивом.
Хотя уже есть принятый ответ, похоже, что он сосредоточен на C ++, а вопрос помечен java . В Java первым примером, который приходит на ум для такого рода вещей, является Arrays.asList , который возвращает, по сути, представление массива, заключенного в список. Базовый массив и список все еще связаны; изменения в массиве отражаются в списке и наоборот. Однако массив, возвращаемый методом toArray списка, не зависит от исходного массива и списка:
String[] wordArray = {"one", "fine", "day"};
List<String> wordList = Arrays.asList(wordArray);
// changes to the array are visible in the list
System.out.println(wordList); // prints "[one, fine, day]"
wordArray[1] = "horrible";
System.out.println(wordList); // prints "[one, horrible, day]"
// changes to the list are visible in the array
wordList.set(1, "beautiful");
System.out.println(wordArray[1]); // prints "beautiful"
// but changes to the list or array don't affect the
// result from the list's toArray method.
String[] moreWords = wordList.toArray(new String[] {});
wordList.set(0, "the");
wordArray[1] = "best";
for (int i=0; i<3; i++) {
System.out.println(moreWords[i]); // prints "one", "beautiful", and "day"
}
Все это говорит о том, что нет гарантии, что каждый разработчик библиотеки будет следовать этому соглашению, поэтому вам все равно нужно проверить документацию, чтобы выяснить, будет ли это поведение, которое вы получите от неизвестного кода.
Другое место, которое я видел как методы ... (), часто используемые в преобразовании типов в подтипы. Например, если у вас есть перечислимый набор подтипов, то вы можете получить такой код:
/**
* Every Node is either an ANode or a BNode.
*/
interface Node {
/**
* Returns this Node as an ANode.
*
* @return this node
*/
default ANode asANode() {
if (this instanceof ANode) {
return (ANode) this;
}
else {
throw new UnsupportedOperationException();
}
// Or, in Java8 style, perhaps:
// return Optional.of(this)
// .filter(ANode.class::isInstance)
// .map(ANode.class::cast)
// .orElseThrow(UnsupportedOperationException::new);
}
/**
* Returns this Node as a BNode.
*
* @return this node
*/
default BNode asBNode() {
if (this instanceof BNode) {
return (BNode) this;
}
else {
throw new UnsupportedOperationException();
}
}
}
Разница, которую я заметил (только сейчас, подумав об этом)
Итак, мы видим AsInteger и AsString и видим ToArray и ToStringList.
Это подразумевает преобразование, которое имеет смысл (это движение, процесс). Как подразумевается представление, способ выражения исходного объекта.
Еще один способ взглянуть на это:
И затем есть "предшествующий уровень техники" (или наследство), чтобы иметь дело с. До того, как языки были полностью OO с нуля, у вас были бы библиотечные функции, такие как StrToInt () и IntToStr (). Они выполняли преобразования, они были операциями, поэтому имело смысл называть их SomethingToSomethingelse (). В конце концов, To более активен, чем As. Я особенно думаю о Delphi здесь.
Когда C # был спроектирован с амбициями полностью перейти на OO, имело смысл иметь метод для целочисленного объекта, который преобразует целое число в строку. Хотя у нас также есть класс Convert, преобразование в строку настолько распространено, что он стал виртуальным методом для объекта. Дизайнеры, возможно, решили, что ToString будет более знакомым людям из старой парадигмы, и, возможно, именно поэтому мы получили виртуальный метод ToString (), а не виртуальное свойство AsString.
toString()
?