Pergunta

Suponha que eu tenho um 'Aplicação' classe. A fim de ser inicializado leva certas configurações no construtor. Vamos supor também que o número de configurações é tantas que é convincente para colocá-los em uma classe própria.

Compare os dois seguintes implementações deste cenário.

Implementação 1:

class Application 
{
   Application(ApplicationSettings settings) 
   {
       //Do initialisation here
   }
}

class ApplicationSettings 
{
   //Settings related methods and properties here
}

Implementação 2:

class Application 
{
   Application(Application.Settings settings) 
   {
       //Do initialisation here
   }

   class Settings 
   {
      //Settings related methods and properties here
   }
}

Para mim, a segunda abordagem é muito preferível. É mais legível porque enfatiza fortemente a relação entre as duas classes. Quando eu escrever código para qualquer classe Application instanciar, a segunda abordagem vai olhar mais bonito.

Agora é só imaginar a classe de configurações em si, por sua vez tinha alguma classe semelhante "relacionados" e essa classe, por sua vez fez isso também. Ir apenas três desses níveis e a nomeação classe sai fora de controle no caso 'não-aninhada'. Se você ninho, no entanto, as coisas ainda ficar elegante.

pessoas Apesar do exposto acima, que li dizem sobre StackOverflow que classes aninhadas são justificados somente se eles não são visíveis para o mundo exterior; isto é, se eles são usados ??apenas para a aplicação interna da classe que contém. A objeção comumente citado é o inchaço do tamanho de conter arquivo de origem de classe, mas classes parciais é a solução perfeita para esse problema.

A minha pergunta é, por que estamos cautelosos com o uso "exposta publicamente" de classes aninhadas? Existem outros argumentos contra tal uso?

Foi útil?

Solução

Eu acho que é bom. Este é basicamente o padrão do construtor, e usando classes aninhadas funciona muito bem. Ele também permite o acesso construtor membros privados da classe externa, que pode ser muito útil. Por exemplo, você pode ter um método Desenvolver ao construtor que chama um construtor privado na classe externa que leva uma instância do construtor:

public class Outer
{
    private Outer(Builder builder)
    {
        // Copy stuff
    }

    public class Builder
    {
        public Outer Build()
        {
            return new Outer(this);
        }
    }
}

que garante que o única maneira de construir uma instância da classe externa é através do construtor.

Eu uso um padrão muito parecido com isso no meu C # porta de Protocol Buffers.

Outras dicas

Você pode usar namespaces para relacionar as coisas que são ... relacionadas.

Por exemplo:

namespace Diner
{
    public class Sandwich
    {
        public Sandwich(Filling filling) { }
    }

    public class Filling { }
}

A vantagem deste sobre o uso de classes como se fossem namespaces é que você pode usar opcionalmente using no lado chamando para abreviar coisas:

using Diner;

...

var sandwich = new Sandwich(new Filling());

Se você usar a classe Sandwich como se fosse um espaço de nomes para Filling, você tem que usar o nome Sandwich.Filling completo para se referir a Filling.

E como é que você vai dormir à noite sabendo que?

Você pode querer verificar o que Microsoft tem que dizer sobre o tema. Basicamente, é uma questão de estilo, eu diria.

Outro exemplo prático que eu tenho para um uso válido de classes aninhadas públicas é no padrão MVC quando eu uso um viewmodel com uma propriedade IEnumerable. por exemplo:

public class OrderViewModel
{
public int OrderId{ get; set; }
public IEnumerable<Product> Products{ get; set; }

public class Product {
public string ProductName{ get; set; }
public decimal ProductPrice{ get; set; }
}

}

Eu usá-lo porque eu não quero classe Product ser reutilizados fora porque ele é personalizado apenas para esse viewmodel específica que contém. Mas eu não posso torná-lo privado porque a propriedade Products é público.

Eu uso principalmente classes aninhadas para acesso fine-tuning para o nested e / ou a classe contêiner.

Uma coisa a lembrar é que uma definição de classe aninhada é basicamente um membro da classe, e terá acesso a todas as variáveis ??privadas do contêiner.

Você também pode usar isso para o uso de uma classe específica de controle.

Exemplo:

public abstract class Outer
{
  protected class Inner
  {
  }
}

Agora, neste caso, o usuário (de sua classe) só pode acessar a classe interna, se ele implementa exterior.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top