Existe uma regra geral para quando codificar um método estático versus um método de instância?

Estou aprendendo Java (e OOP) e, embora possa ser irrelevante para onde estou agora, gostaria de saber se o SO poderia compartilhar algumas armadilhas comuns ou boas práticas de design.

Uma coisa importante a lembrar é que os methods estáticos não podem ser substituídos por uma subclass. Referências a um método estático em seu código essencialmente vinculam a essa implementação. Ao usar methods de instância, o comportamento pode ser variado com base no tipo da instância. Você pode aproveitar o polymorphism. Os methods estáticos são mais adequados para tipos utilitários de operações em que o comportamento é definido em pedra. Coisas como a base 64 codificando ou calculando uma sum de verificação, por exemplo.

Eu não acho que nenhuma das respostas chegue ao coração da razão OO de quando escolher uma ou outra. Claro, use um método de instância quando precisar lidar com membros de instância, mas você pode tornar públicos todos os seus membros e, em seguida, codificar um método estático que toma uma instância da class como um argumento. Olá C.

Você precisa pensar sobre as mensagens que o object que você está projetando responde. Esses sempre serão seus methods de instância. Se você pensar sobre seus objects dessa maneira, você quase nunca terá methods estáticos . Membros estáticos estão bem em certas circunstâncias.

Exceções notáveis ​​que vêm à mente são os padrões Factory Method e Singleton (use com moderação). Tenha cuidado quando for tentado a escrever uma class “auxiliar”, pois, a partir daí, é uma tendência escorregadia para a programação procedural.

Se a implementação de um método pode ser expressa completamente em termos da interface pública (sem downcasting) de sua class, então pode ser um bom candidato para um método “utilitário” estático. Isso permite que você mantenha uma interface mínima enquanto ainda fornece os methods de conveniência que os clientes do código podem usar muito. Como explica Scott Meyers , essa abordagem incentiva o encapsulamento ao minimizar a quantidade de código afetada por uma alteração na implementação interna de uma class. Aqui está outro artigo interessante de Herb Sutter escolhendo std :: basic_string decidindo quais methods devem ser membros e o que não deve.

Em uma linguagem como Java ou C ++, admito que os methods estáticos tornam o código menos elegante, então ainda há uma desvantagem. Em C #, os methods de extensão podem oferecer o melhor dos dois mundos.

Se a operação precisar ser substituída por uma subclass por algum motivo, é claro que deve ser um método de instância, caso em que você precisará pensar em todos os fatores que influenciam o design de uma class para inheritance.

Minha regra geral é: se o método executa algo relacionado a uma instância específica de uma class, independentemente de precisar usar variables ​​de instância de class. Se você puder considerar uma situação em que talvez seja necessário usar um determinado método sem necessariamente se referir a uma instância da class, o método definitivamente deve ser estático (class). Se esse método também precisar usar variables ​​de instância em certos casos, provavelmente será melhor criar um método de instância separado que chame o método estático e transmita as variables ​​de instância. Em termos de desempenho, acredito que exista uma diferença insignificante (pelo menos no .NET, embora eu imagino que seria muito semelhante para o Java).

Se você mantiver estado (um valor) de um object e o método for usado para acessar ou modificar o estado, então você deve usar um método de instância.

Mesmo que o método não altere o estado (uma function de utilidade), recomendo que você use um método de instância. Principalmente porque desta forma você pode ter uma subclass que executa uma ação diferente.

Para o resto, você poderia usar um método estático.

🙂

Sua escolha padrão deve ser um método de instância.

Esta discussão parece relevante: o método pode ser feito estático, mas deveria? A diferença entre C # e Java não afetará sua relevância (eu acho).

Se ele usa uma variável de instância, deve ser um método de instância.

Se não, cabe a você, mas se você se encontrar com muitos methods estáticos e / ou variables ​​estáticas não-finais, você provavelmente desejará extrair todo o material estático em uma nova instância de class. (Um monte de methods estáticos e membros é um singleton, mas um muito chato, ter um object singleton real seria melhor – um object regular que acontece de ser um dos melhores!).

Basicamente, a regra geral é se ela usa algum dado específico para o object, instância. Portanto, Math.max é estático, mas BigInteger.bitCount () é uma instância. Obviamente, fica mais complicado como o seu modelo de domínio, e há casos de linha de borda, mas a idéia geral é simples.

Eu usaria um método de instância por padrão. A vantagem é que o comportamento pode ser substituído em uma subclass ou se você estiver codificando em relação a interfaces, uma implementação alternativa do colaborador pode ser usada. Isso é realmente útil para flexibilidade no teste de código.

Referências estáticas são incorporadas à sua implementação e não podem ser alteradas. Eu acho estático útil para methods de utilidade curtos. Se o conteúdo do seu método estático for muito grande, você pode pensar em dividir a responsabilidade em um ou mais objects separados e permitir que eles colaborem com o código do cliente como instâncias de object.

IMHO, se você pode torná-lo um método estático (sem ter que mudar sua estrutura), em seguida, torná-lo um método estático. É mais rápido e mais simples.

Se você sabe que vai querer replace o método, sugiro que você escreva um teste de unidade onde você realmente faz isso e por isso não é mais apropriado torná-lo estático. Se isso parece muito trabalho duro, então não faça disso um método de instância.

Geralmente, você não deve adicionar funcionalidade assim que você imaginar um uso um dia (dessa forma a loucura está), você deve apenas adicionar funcionalidades que você realmente precisa.

Para uma explicação mais longa …

http://en.wikipedia.org/wiki/You_Ain%27t_Gonna_Need_It

http://c2.com/xp/YouArentGonnaNeedIt.html

O problema com os methods estáticos é que você está quebrando um dos princípios orientados a objects como você está acoplado a uma implementação. Você quer apoiar o princípio do fechamento aberto e fazer com que sua class implemente uma interface que descreva a dependência (em um sentido abstrato comportamental) e depois que suas classs dependam dessa interface. Muito mais fácil de estender depois desse ponto daqui para frente. ..

Meus methods estáticos são sempre um dos seguintes:

  1. Métodos “auxiliares” privados que avaliam uma fórmula útil apenas para essa class.
  2. Métodos de fábrica ( Foo.getInstance() etc.)
  3. Em uma class “utility” que é final, tem um construtor privado e contém nada além de methods estáticos públicos (por exemplo, com.google.common.collect.Maps )

Eu não farei um método estático apenas porque ele não se refere a nenhuma variável de instância.