2012-08-22 27 views
15

yo estaba pasando por algo de código y vi esto:Por qué tienen clase estática pública dentro de una clase

public class A { 
    public A(SomeObject obj) { 
     //Do something 
    } 
    //Some stuff 
    public static class B { 
    //Some other stuff 
    } 
} 

Me preguntaba ya que incluso la clase interna es public ¿por qué es tan anidado y no una clase separada? Además, ¿puedo hacer esto aquí: new A.B(SomeObject)? Siento que esto derrota el propósito de una clase estática pero vi esta implementación también, así que quería saber.

Respuesta

17

Me preguntaba, ya que incluso la clase interna es pública ¿por qué tenerlo como anidado y no una clase separada?

Eso es realmente una pregunta para quien escribió la clase. Sin embargo, puede permitir que la clase externa actúe como un "mini-espacio de nombres": si la clase anidada es solo útil en el contexto de la clase externa, parece razonable. Indica acoplamiento apretado deliberado entre las dos clases.Me veo más a menudo esto en el contexto de la Builder:

Foo foo = new Foo.Builder().setBar(10).build(); 

Aquí tiene sentido para mí tener Foo.Builder anidada dentro de Foo más que como una clase de pares que presumiblemente se llamaría FooBuilder.

Tenga en cuenta que también ofrece algunas diferencias de visibilidad en comparación con las clases no relacionadas.

Además, ¿puedo hacer esto aquí: new A.B(SomeObject)?

No, porque B no tiene un constructor con un parámetro SomeObject - solamente A va (en el ejemplo que hemos dado).

me siento de esta derrota el propósito de una clase estática

Usted debe tratar de llegar a exactamente lo que consideran el propósito de una clase estática a ser, y de qué manera esta derrota que propósito. Actualmente esa es una declaración demasiado vaga para ser discutida de manera realista.

+0

buena explicación Jon ... +1 de mí ... – pratikabu

5

usted tendría una clase interna como éste, así

  • que pueda mantener una clase que sólo existe para apoyar a la clase externa encapsulado.
  • desea poder acceder a private miembros de la clase externa u otras clases anidadas.
  • desea que una clase anidada con campos estáticos (una razón débil que sé;)
  • que tienen una clase con un nombre muy genérico como Lock o Sync que no quiere mezclarse con otras clases de la misma nombre utilizado por las clases en el mismo paquete.

puedo hacer esto aquí: nuevo A.B (SomeObject)?

Puedes.

me siento de esta derrota el propósito de una clase estática

que se necesita tiempo para acostumbrarse, pero una vez que comience es posible que tenga problemas para no entregar todo su programa en una file.java;)

2

Me preguntaba, ya que incluso la clase interna es pública ¿por qué tenerlo como anidado y no una clase separada?

Tener un vistazo a este tema: Why strange naming convention of "AlertDialog.Builder" instead of "AlertDialogBuilder" in Android

Además, puedo hacer esto aquí: nueva A.B (SomeObject)?

(Actualización) No, no puede hacer esto, ya que B no tiene un constructor que solicite SomeObject.

Espero que esto ayude.

+0

Tu conexión apunta actualmente a la última respuesta. Sugeriría este enlace en su lugar http://stackoverflow.com/questions/11810345/why-strange-namimg-convention-of-alertdialog-builder-instead-of-alertdialogbu –

+0

Creo que su respuesta es incorrecta para el 'nuevo AB (SomeObject) 'de acuerdo con las otras respuestas que figuran a continuación, que en realidad tiene sentido ya que no hay ningún constructor para la clase estática – noMAD

+0

Lo siento, mi mal, tienes razón, he actualizado. –

2

1. A static inner clase se conoce como Top-Level Clase.

2. Este static class tiene acceso directo con el método y las variables estáticas de clase Su exterior .

3. Usted tendrá que inicializar el static Inner class de esta manera desde el exterior ...

A a = new A(); 
    A.B b = new A.B(); 

4.new A.B(SomeObject)no funcionará ... porque Don' t tiene un constructor con SomeObject como parámetro ...

5. Pero cuando la clase interna es no estática, entonces tiene una referencia implícita a la clase externa.

6. La clase externa e interna puede se extiende a diferentes clases.

7. Un interface's method pueden implementarse más de una vez en diferentes o misma manera, utilizando la clase interna.

2

Este patrón se utiliza muy a menudo con el patrón del generador. No solo aclara la relación entre una clase y su constructor, sino que también oculta el constructor/fábrica feo del generador y hace que el constructor sea más legible. Por ejemplo, en caso de que necesite que su objeto construido tenga propiedades opcionales y no opcionales.

public class AnObject { 
    public static class AnObjectBuilder { 

     private AnObject anObject; 

     private AnObjectBuilder() { 
     } 

     private void newAnObjectWithMandatory(String someMandatoryField, ...) { 
      anObject = new AnObject(someMandatoryField,...) 
     } 

     public AnObjectBuilder withSomeOptionalField(String opt) { 
      ... 
     } 
    } 

    public static AnObjectBuilder fooObject() { 
     return (new AnObjectBuilder()).newAnObjectWithMandatory("foo") 
    } 

    public static AnObjectBuilder barObject() { 
     return (new AnObjectBuilder()).newAnObjectWithMandatory("bar") 
    } 
} 

De esta manera el código de cliente tiene que llamar primero al método estático de la clase AnObjectBuilder y luego utilizar los métodos constructor opcionales:

AnObject.fooObject("foo").withSomeOptionalField("xxx").build(); sin crear el objeto constructor.

Bastante legible :)

+0

Gracias por el ejemplo. – noMAD

Cuestiones relacionadas