Qual é a diferença entre os prefixos do nome do método “to” e “as”? [fechadas]

75

Qual é a diferença entre "a" e "como" prefixo do nome do método como

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

Quando usar o que ao projetar um método?

    
por Daniel Hári 04.07.2017 / 20:17
fonte

4 respostas

118

Espera-se que uma função toXYZ() faça uma conversão e retorne um novo objeto independente (embora a imutabilidade permita a otimização, java.lang.String.toString() apenas retorna o objeto).
Como exemplo, em C ++ temos std::bitset::to_ulong() que pode falhar facilmente, e um todo infinidade de to_string() , todos fazendo um (mais ou menos) conversão complexa e alocação de memória.

Espera-se, por outro lado, que uma função asXYZ() retorne uma visão (potencialmente diferente) da origem, fazendo um trabalho mínimo.
Como exemplo, em C ++ temos std::as_const() que apenas retorna uma referência constante, e quanto mais envolvido std::forward_as_tuple que também se refere aos seus argumentos por referência.

    
por 04.07.2017 / 20:20
fonte
12

Honestamente, isso pode estar apenas indicando inconsistência. Se observar objetos de biblioteca padrão no Smalltalk, por exemplo, todos os métodos que fazem "conversões complexas" ou "retornam representações simples em outro tipo" são prefixados com as , como em asString , asFloat , asSeconds , e o método padrão para converter qualquer coisa em qualquer outra coisa, as: aClass .

Em Ruby, os mesmos tipos de métodos são prefixados com to_ , como em to_s , to_a , to_h , abreviação de string , array e hash , respectivamente.

Nenhuma biblioteca padrão parece diferenciar entre diferentes tipos de conversão, provavelmente porque deve ser considerada como um detalhe de implementação.

No entanto, em Java, vemos muita confusão. Como você mencionou, há toString , asList e assim por diante. Eu acredito que estas são apenas uma inconsistência de nomenclatura, porque se você tentar definir um significado diferente para cada prefixo, você sempre encontrará um contra-exemplo em algum outro lugar na biblioteca padrão.

Então, em todo caso, eu diria que o importante é você e sua equipe escolherem um prefixo e usá-lo consistentemente em todo o código. Consistência é a chave, então as pessoas não são deixadas a pensar, como você teve que fazer.

    
por 05.07.2017 / 05:13
fonte
5

Embora já exista uma resposta aceita, ela parece se concentrar em C ++, enquanto a pergunta é marcada com java . Em Java, o primeiro exemplo que vem à mente para esse tipo de coisa é Arrays.asList , que retorna, essencialmente, uma visão de uma matriz, agrupada em uma lista. A matriz subjacente e a lista ainda estão conectadas; as mudanças na matriz são refletidas na lista e vice-versa. No entanto, a matriz retornada pelo método toArray da lista é independente da matriz original e da 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"
}

Tudo isso dito, não há garantia de que todos os desenvolvedores de bibliotecas seguem essa convenção, então você ainda precisa verificar a documentação para descobrir se esse é o comportamento que você obterá de código desconhecido.

O outro lugar em que vi os métodos ... () usados com frequência é em tipos de downcasting para subtipos. Por exemplo, se você tiver um conjunto enumerado de subtipos, poderá acabar com o 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();
      }
    }
  }
    
por 05.07.2017 / 18:03
fonte
0

A diferença que notei (agora pensando nisso) é

  • Geralmente, converte em um tipo de referência diferente (um objeto complexo)
  • Como normalmente retorna um tipo de valor simples

Então, vemos AsInteger e AsString e vemos ToArray e ToStringList.

Para implicar uma conversão, o que faz sentido (é um movimento, um processo). Como implica uma representação, uma maneira de expressar o objeto original.

Outra maneira de ver isso:

  • To é uma operação, então você usaria para métodos.
  • Como é uma representação simples, você a usaria para propriedades.

E depois há "arte prévia" (ou legado) para lidar. Antes que os idiomas fossem totalmente OO, você teria funções de biblioteca como StrToInt () e IntToStr (). Eles realizavam conversões, eram operações, por isso fazia sentido chamá-las de SomethingToSomethingelse (). Afinal, To é mais ativo que As. Eu estou particularmente pensando em Delphi aqui.

Quando o C # foi projetado com a ambição de ir até o OO, fazia sentido ter um método no objeto now integer que converteria o inteiro em uma string. Embora também tenhamos uma classe Convert, a conversão para string é tão comum que foi feito um método virtual no objeto. Os designers podem ter imaginado que o ToString seria mais familiar para as pessoas do antigo paradigma e talvez por isso tenhamos um método virtual ToString () e não uma propriedade virtual AsString.

    
por 04.07.2017 / 21:35
fonte

Tags