¿Cuál es la diferencia entre los prefijos de nombre de método "to" y "as"? [cerrado]

74

¿Cuál es la diferencia entre "a" y "como" prefijos de nombre de método como

  • toList (),
  • asList (),
  • etc ...

¿Cuándo usar cuál al diseñar un método?

    
pregunta Daniel Hári 04.07.2017 - 20:17

4 respuestas

117

Se espera que una función toXYZ() realice una conversión y devuelva un nuevo objeto independiente (aunque la inmutabilidad permite la optimización, java.lang.String.toString() solo devuelve el objeto).
Como ejemplo, en C ++ tenemos std::bitset::to_ulong() que puede fallar fácilmente, y todo gran cantidad de to_string() , todos haciendo un (más o menos) Conversión compleja y asignación de memoria.

Por otra parte, se espera que una función asXYZ() devuelva una vista (potencialmente diferente) de la fuente, realizando un trabajo mínimo.
Como ejemplo, en C ++ tenemos std::as_const() que simplemente devuelve una referencia constante, y más involucrados std::forward_as_tuple que también hace referencia a sus argumentos por referencia.

    
respondido por el Deduplicator 04.07.2017 - 20:20
12

Honestamente, puede que solo sea una inconsistencia de nombres. Si observa los objetos de la biblioteca estándar en Smalltalk, por ejemplo, todos los métodos que realizan "conversiones complejas" o "devuelven representaciones simples en otro tipo" tienen el prefijo as , como en asString , asFloat , asSeconds , y el método estándar para convertir cualquier cosa en otra cosa, as: aClass .

En Ruby, los mismos tipos de métodos tienen el prefijo to_ , como en to_s , to_a , to_h , abreviatura de string , array y hash respectivamente.

Ninguna de las bibliotecas estándar parece diferenciar entre diferentes tipos de conversiones, probablemente porque debería considerarse como un detalle de implementación.

Sin embargo, en Java vemos mucha confusión. Como mencionaste, hay toString , asList , y así sucesivamente. Creo que estos son solo una incoherencia de nombres, porque si intentas definir un significado diferente para cada prefijo, siempre encontrarás un contraejemplo en otra parte de la biblioteca estándar.

En cualquier caso, diría que lo importante es que usted y su equipo escojan un prefijo y lo usen de manera consistente en todo el código. La consistencia es la clave, por lo que las personas no se quedan como para preguntarse, como usted tenía que hacerlo.

    
respondido por el MichelHenrich 05.07.2017 - 05:13
5

Si bien ya hay una respuesta aceptada, parece centrarse en C ++, mientras que la pregunta está etiquetada con java . En Java, el primer ejemplo que viene a la mente para este tipo de cosas es Arrays.asList , que devuelve, esencialmente, una vista de una matriz, envuelta en una lista. Sin embargo, la matriz subyacente y la lista todavía están conectadas; los cambios en la matriz se reflejan en la lista, y viceversa. Sin embargo, la matriz devuelta por el método toArray de la lista es independiente de la matriz original y de la lista:

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"
}

Dicho todo esto, no hay garantía de que todos los desarrolladores de bibliotecas sigan esta convención, por lo que aún debe consultar la documentación para averiguar si este es el comportamiento que obtendrá de un código desconocido.

El otro lugar en el que he visto como ... () los métodos que se usan con frecuencia es en los tipos de conversión descendente a subtipos. Por ejemplo, si tiene un conjunto de subtipos enumerados, entonces podría terminar con un código como:

  /**
   * 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();
      }
    }
  }
    
respondido por el Joshua Taylor 05.07.2017 - 18:03
0

La diferencia que noté (solo ahora al pensarlo) es

  • Para convertir normalmente a un tipo de referencia diferente (un objeto algo complejo)
  • Como normalmente devuelve un tipo de valor simple

Entonces vemos AsInteger y AsString y vemos ToArray y ToStringList.

Para implica una conversión, lo que tiene sentido (es un movimiento, un proceso). Como implica una representación, una forma de expresar el objeto original.

Otra forma de ver esto:

  • Para es una operación, por lo que lo usarías para los métodos.
  • Como es una representación simple, entonces la usarías para las propiedades.

Y luego está el "arte anterior" (o legado) con el que lidiar. Antes de que los idiomas fueran totalmente OO desde el principio, tendrías funciones de biblioteca como StrToInt () e IntToStr (). Hicieron conversiones, eran operaciones, así que tenía sentido llamarlos SomethingToSomethingelse (). Después de todo, To es más activo que As. Estoy pensando particularmente en Delphi aquí.

Cuando C # se diseñó con la ambición de ir OO todo el camino, tenía sentido tener un método en el objeto ahora entero que convertiría el número entero en una cadena. Aunque también tenemos una clase Convert, la conversión a cadena es tan común que se convirtió en un método virtual en el objeto. Los diseñadores pueden haber imaginado que ToString sería más familiar para las personas del antiguo paradigma y tal vez es por eso que obtuvimos un método virtual ToString () y no una propiedad virtual AsString.

    
respondido por el Martin Maat 04.07.2017 - 21:35

Lea otras preguntas en las etiquetas