Por que um construtor deve ser uma classe interna em vez de em seu próprio arquivo de classe?

24

Muitos Builder Patternexemplos compõem a Builderclasse interna do objeto que ele constrói.

Isso faz algum sentido, pois indica o que as Buildercompilações. No entanto, em uma linguagem de tipo estaticamente, sabemos o que é Builderconstruído.

Por outro lado, se Builderfor uma classe interna, você deve saber qual classe a Buildercompilação sem olhar para dentro da Builder.

Além disso, ter o construtor como uma classe interna reduz o número de importações, pois ele pode ser referenciado pela classe externa - se você se importa com isso.

E há exemplos práticos em que o Builderestá no mesmo pacote, mas não em uma classe interna, como StringBuilder. Você sabe que o Builder deve criar um Stringporque é assim chamado.

Dito isto, a única boa razão para pensar em fazer uma Builderclasse interna é que você sabe o que é a classe Buildersem saber seu nome ou depender de convenções de nomenclatura. Por exemplo, se StringBuilderfosse uma classe interna de Stringeu provavelmente saberia que existia mais cedo do que existia (especulativo).

Existem outras razões para fazer da Builderclasse uma parte interna ou se resume apenas à preferência e ao ritual?

Nathanial
fonte

Respostas:

30

Eu acho que a razão para fazer isso é para que a classe interna (o Construtor) possa acessar membros privados da classe que está criando.

Em http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

Classes aninhadas não estáticas (classes internas) têm acesso a outros membros da classe envolvente, mesmo que sejam declaradas privadas.

...

Considere duas classes de nível superior, A e B, em que B precisa acessar membros de A que, de outra forma, seriam declarados particulares. Ao ocultar a classe B na classe A, os membros de A podem ser declarados privados e B pode acessá-los.

...

Assim como os métodos e variáveis ​​de instância, uma classe interna é associada a uma instância de sua classe envolvente e tem acesso direto aos métodos e campos desse objeto.

Aqui está um código para tentar ilustrar isso:

class Example {

    private int x;

    public int getX() { return this.x; }

    public static class Builder {

        public Example Create() {
            Example instance = new Example();
            instance.x = 5; // Builder can access Example's private member variable
            return instance;
        }
    }
}

Como uma classe estática, o Builder não possui uma instância específica de Example à qual está vinculada. No entanto, dada uma instância do Exemplo (ou uma que ele mesmo cria), o Builder ainda pode acessar os membros privados dessa instância.

Aprendiz do Dr. Wily
fonte
Ótima resposta, isso faz sentido! No entanto, os padrões do construtor geralmente têm uma classe interna estática e só poderiam acessar membros privados estáticos da classe externa. Se você tivesse um construtor para uma classe instanciada, isso seria estranho.
Nathanial 23/01
1
@Nathanial não em todos, variáveis de instância privadas também são acessíveis: ideone.com/7DyjDR
amon
1
@nathanial: Sim, mas o construtor não está manipulando a classe; está manipulando um objeto da classe que o próprio construtor instanciou.
Robert Harvey
@ amon eu vejo o que você fez lá. Obrigada pelo esclarecimento!
precisa saber é o seguinte
Especificamente, fornece ao construtor acesso a um construtor privado para a classe que está sendo construída, permitindo que essa classe seja imutável (todos os campos finais) e instanciada apenas pelo construtor.
Matthew McPeak
1

Não há "deveria" neste caso. Definir um construtor dentro de outra classe ou separá-lo é ortogonal ao padrão Construtor. Muitos exemplos fazem isso devido à conveniência de apresentar o código em um arquivo consistente (também para acessar membros particulares, mas isso também depende do contexto). Sinta-se livre para fazer o contrário

AZ01
fonte
Não sei por que essa resposta foi rejeitada, por qualquer outro motivo que não seja "porque não é assim que fazemos em Java". O Padrão do Construtor fornece um wrapper em torno de um construtor que usa vários parâmetros. Se o construtor usar esses parâmetros, não será necessário que o objeto Builder acesse membros privados.
22616 Greg Burghardt