Pergunta sobre constructor, constructor-overloading, overloading, java – Sobrecarga de construtor em Java - melhor prática

100

Existem alguns tópicos semelhantes a este, mas não consegui encontrar um com uma resposta suficiente.

Eu gostaria de saber qual é a melhor prática para sobrecarga de construtor em Java. Eu já tenho meus próprios pensamentos sobre o assunto, mas gostaria de ouvir mais conselhos.

Estou me referindo a sobrecarga de construtor em uma classe simples e sobrecarga de construtor ao herdar uma classe já sobrecarregada (ou seja, a classe base tem construtores sobrecarregados).

Obrigado :)

Sua resposta

5   a resposta
6

Se você tem uma classe muito complexa com muitas opções, das quais apenas algumas combinações são válidas, considere o uso de um Builder. Funciona muito bem tanto em codificação como logicamente.

O Construtor é uma classe aninhada com métodos projetados apenas para definir campos e, em seguida, o construtor ComplexClass considera apenas um construtor como um argumento.

Edit: O construtor ComplexClass pode garantir que o estado no Builder seja válido. Isso é muito difícil se você usar setters no ComplexClass.

Concordo muito usar o padrão de construtor, construtores sobrecarregados como o OP é realmente má idéia, pois não o princípio da menor surpresa. Martin Spamer
2

Isso realmente depende do tipo de classes, pois nem todas as classes são criadas iguais.

Como diretriz geral eu sugeriria 2 opções:

Paravalor e imutável classes (Exception, Integer, DTOs e tal) usamúnico construtor primário como sugerido na resposta acimaPara todo o resto (beans de sessão, serviços, objetos mutáveis, entidades JPA e JAXB e assim por diante), useconstrutor padrão apenas com padrões sensíveis em todas as propriedades para que possa ser usado sem configuração adicional
0

Bem, aqui está um exemplo para construtores sobrecarregados.

public class Employee
{
   private String name;
   private int age;

   public Employee()
   {
      System.out.println("We are inside Employee() constructor");
   }

   public Employee(String name)
   {
      System.out.println("We are inside Employee(String name) constructor");
      this.name = name;
   }

   public Employee(String name, int age)
   {
      System.out.println("We are inside Employee(String name, int age) constructor");
      this.name = name;
      this.age = age;
   }

   public Employee(int age)
   {
      System.out.println("We are inside Employee(int age) constructor");
      this.age = age; 
   }

   public String getName()
   {
      return name;
   }

   public void setName(String name)
   {
      this.name = name;
   }

   public int getAge()
   {
      return age;
   }

   public void setAge(int age)
   {
      this.age = age;
   }
}

No exemplo acima, você pode ver construtores sobrecarregados. O nome dos construtores é o mesmo, mas cada construtor possui parâmetros diferentes.

Aqui estão alguns recursos que lançam mais luz sobre sobrecarga de construtor em java,

Construtores.

Explicação do construtor.

Parece muito menos esforço foi colocado em escrever esta resposta. E o OP sabe o que é sobrecarga de construtor. A resposta explica exatamente isso. rockydgeekgod
159

Embora não haja "diretrizes oficiais", eu sigo o princípio do KISS e do DRY. Torne os construtores sobrecarregados o mais simples possível, e a maneira mais simples é que eles só chamam isso (...). Dessa forma, você só precisa verificar e manipular os parâmetros uma vez e apenas uma vez.

public class Simple {

    public Simple() {
        this(null);
    }

    public Simple(Resource r) {
        this(r, null);
    }

    public Simple(Resource r1, Resource r2) {
        // Guard statements, initialize resources or throw exceptions if
        // the resources are wrong
        if (r1 == null) {
            r1 = new Resource();
        }
        if (r2 == null) {
            r2 = new Resource();
        }

        // do whatever with resources
    }

}

Do ponto de vista do teste de unidade, será fácil testar a classe, já que você pode colocar os recursos nela. Se a classe tiver muitos recursos (ou colaboradores como alguns OO-geeks chamam), considere uma destas duas coisas:

Faça uma classe de parâmetro
public class SimpleParams {
    Resource r1;
    Resource r2;
    // Imagine there are setters and getters here but I'm too lazy 
    // to write it out. you can make it the parameter class 
    // "immutable" if you don't have setters and only set the 
    // resources through the SimpleParams constructor
}

O construtor no Simple só precisa dividir oSimpleParams parâmetro:

public Simple(SimpleParams params) {
    this(params.getR1(), params.getR2());
}

… Ou fazerSimpleParams um atributo:

public Simple(Resource r1, Resource r2) {
    this(new SimpleParams(r1, r2));
}

public Simple(SimpleParams params) {
    this.params = params;
}
Faça uma aula de fábrica

Faça uma classe de fábrica que inicialize os recursos para você, o que é favorável se a inicialização dos recursos for um pouco difícil:

public interface ResourceFactory {
    public Resource createR1();
    public Resource createR2();
}

O construtor é então feito da mesma maneira que com a classe do parâmetro:

public Simple(ResourceFactory factory) {
    this(factory.createR1(), factory.createR2());
} 
Faça uma combinação de ambos

Sim ... você pode misturar e combinar os dois lados, dependendo do que é mais fácil para você no momento. As classes de parâmetros e classes de fábrica simples são praticamente a mesma coisa, considerando oSimple classe que eles são usados ​​da mesma maneira.

é possível ter múltiplos construtores com 1 parâmetro de tipo diferente em cada um? Como - novo Objeto (int aa) / novo Objec (String bb)? Botea Florin
+1 post muito legal user12345613
Eu notei neste, bem como outros exemplos que as definições do construtor são escritas cuja ordem usa menos para a maioria dos argumentos na chamada do construtor. Este é o estilo padrão de Java? Por quê ?: Na minha opinião, faria sentido fazer da maneira oposta, da mesma forma que a primeira definição de construtor que você deve ver é aquela que contém todos os detalhes. Josie Thompson
@JosieThompson Isso não está definido em nenhum padrão, tanto quanto eu sei. Concordo que ter o construtor completo em primeiro lugar é útil para ver rapidamente todos os parâmetros de um método; ordená-los por contagem de argumentos, no entanto, permite seguir as chamadas sobrecarregadas na página, o que pode parecer mais natural quando você considera como lemos e escrevemos código. Matt
73

Eu acho que a melhor prática é terúnico construtor primário ao qual os construtores sobrecarregados se referem chamandothis() com os padrões de parâmetros relevantes. A razão para isto é que torna muito mais claro o que é oestado construído do objeto é - realmente você pode pensar no construtor primário como oapenas construtor real, os outros apenas delegam para ele

Um exemplo disso pode serJTable - o construtor principal leva umTableModel (mais modelos de coluna e seleção) e os outros construtores chamam esse construtor primário.

Para subclassesonde a superclasse já tem construtores sobrecarregados, Eu tenderia a supor que é razoável tratar qualquer um dos construtores da classe pai comoprimário e acho que é perfeitamente legítimo não ter um único construtor principal. Por exemplo, ao estenderException, Eu costumo fornecer 3 construtores, um levando apenas umString mensagem, uma tomando umaThrowable causa e o outro levando os dois. Cada um desses construtores chamasuper diretamente.

@Tom - há algumas ocasiões em que me desvia dessa prática, mas sempre penso com cuidado ao fazer isso, pois acredito que não ter um únicoprimário constructor é um bom indicador de um design de classe confuso. oxbow_lakes
Eu modifiquei minha resposta deste esclarecimento oxbow_lakes
Sim, isso é o que eu quis dizer. Eyal Roth
Eu acho que isso é desnecessariamente restritivo. Tom Hawtin - tackline

Perguntas relacionadas