2010-05-18 20 views
6

Estoy escribiendo (bueno, completando) una "extensión" de Java que ayudará a la programación de roles.
Traduzco mi código al código de Java con javacc. Mis compiladores agregan a cada clase declarada algún código. He aquí un ejemplo para ser más claro:Java: extensión de clase de objeto

MyClass extends String implements ObjectWithRoles { //implements... is added 
    /*Added by me */ 
    public setRole(...){...} 
    public ... 
    /*Ends of stuff added*/ 
    ...//myClass stuff 
} 

Se añade Implementa .. y los métodos necesarios para cada clase SOLO se declara. Muy duro, ¿no?

Será mejor si escribo mis métodos en una clase y toda la clase amplía esa ... pero ... si la clase ya se extiende otra clase (como en el ejemplo)?

No quiero crear una especie de envoltorio que administre roles porque no quiero que el programador tenga que saber mucho más que Java, pocas palabras reservadas nuevas y su uso.

Mi idea era extender java.lang.Object ... pero no se puede. (¿no?)
¿Otras ideas?

Soy nuevo aquí, pero sigo este sitio así que gracias por leer y todas las respuestas que das. (Pido disculpas por el inglés, soy italiano)

+4

No puede extender 'String'. Es una clase final, no puedes subclasificarla: http://java.sun.com/javase/6/docs/api/java/lang/String.html –

+2

"Mi idea era extender java.lang. Objeto ... pero no se puede. (¿Verdad?) " Hmm, yo diría que cualquier Clase donde no exista objeto de subclases por defecto. –

+1

@James P. Creo que lo que Fabio quería decir es reemplazar a Object con su propia versión actualizada. Y eso se puede hacer, crear una clase base genérica para su propia aplicación y extender todo desde allí. Pero no querrás agregar eso se extiende automáticamente a todo :) – extraneon

Respuesta

6

Si solo es como un proyecto de "investigación" en el que desea explorar cómo funcionaría dicha extensión, podría proporcionar su propia implementación de la clase Object. Simplemente copie la implementación del objeto existente, agregue su método setRole, etc., y proporcione -Xbootclasspath:.:/usr/lib/jvm/java-6-sun/jre/lib/rt.jar como parámetro para el comando java. (Buscaré api-classes en . antes de buscar en el rt.jar real)

+0

Estoy tratando de implementar su solución: agregando el archivo Object en el directorio (.) Java/lang/Object.java modificado con mis métodos. Se compila (por lo que encuentra los métodos), pero cuando intento ejecutarlo obtengo NoSuchMethodError. Utilicé -Xbootclasspath y -classpath con el mismo resultado. (¡Javac funciona incluso sin eso!) –

+0

debe agregar Object.class, no en el directorio '.', sino en el directorio'./Java/lang'. – aioobe

+0

Inglés estúpido ... he hecho que he copiado el java/lang. Compila pero no ejecuta. Lo sentimos .. –

3
  • puedes extender Object - cada clase lo extiende.
  • parece que necesita algo así como herencia múltiple - no existe tal cosa en Java
  • si desea agregar funcionalidad, use la composición del objeto. Es decir,

    YourClass extends Whatever implements ObjectWithRoles { 
        private RoleHandler roleHandler; 
        public RoleHandler getRoleHandler() {..} // defined by the interface 
    } 
    

Y entonces todos los métodos se colocan en el RoleHandler

+0

Cuando dije "extends Object" pensé crear una súper clase de Object, ese no era el término correcto, lo siento. De todos modos su respuesta es útil, voy a verificar si es la solución. Gracias. Fabio F. –

+3

espere, creo que habla sobre extender la clase Object, agregando funcionalidad a TODOS los objetos –

3

Usted debe considerar el uso de la composición en lugar de sucesiones para resolver este problema; de esa manera puede proporcionar la funcionalidad que necesita sin utilizar su "oportunidad única" en la herencia.

Por ejemplo, el JDK proporciona una clase PropertyChangeSupport, que se puede usar para administrar PropertyChangeListener sy el encendido de PropertyChangeEvent s. En situaciones donde desea escribir una clase que dispara PropertyChangeEvent s puede incrustar una variable de instancia PropertyChangeSupport y delegar todas las llamadas a ese método. Este evita la necesidad de heredar y significa que puede complementar una jerarquía de clases existente con nuevas funcionalidades.

public class MyClass extends MySuperClass { 
    private final PropertyChangeSupport support; 

    public MyClass() { 
    this.support = new PropertyChangeSupport(this); 
    } 

    public void addPropertyChangeListener(PropertyChangeListener l) { 
    support.addPropertyChangeListener(l); 
    } 

    protected void firePropertyChangeEvent() { 
    PropertyChangeEvent evt = new ... 
    support.firePropertyChangeEvent(evt); 
    } 
} 
1

Si está haciendo lo que está haciendo, entonces la herencia probablemente no sea la expresión correcta. Es posible que desee considerar el patrón de decorador, mediante el cual crea una clase que toma como parámetro alguna otra clase con menos funcionalidad, y le agrega alguna funcionalidad adicional, delegando a la clase existente la funcionalidad que ya existe. Si la implementación es común para muchos de sus decoradores, es posible que desee considerar poner esa funcionalidad en una clase que pueda compartirse y a la que pueda delegar a todos sus decoradores. Dependiendo de lo que necesite, el doble despacho o la reflexión pueden ser apropiados para crear decoradores similares pero no exactamente iguales para una gran variedad de clases.

Además, como se ha señalado en los comentarios, String se declara "final" y, por lo tanto, no se puede extender. Entonces, realmente deberías considerar una solución mediante la cual delegues/decores objetos.Por ejemplo, puede tener algún objeto que envuelva una cadena y proporcione acceso a la cadena a través de getString() o toString(), pero luego agrega la funcionalidad adicional en la parte superior de la clase String.

Si solo desea asociar algunos objetos con atributos adicionales, use un Map (por ejemplo, HashMap).

+1

1) No existe el "paquete de nivel superior". 2) Las clases denominadas "Objeto" definitivamente * no * se extienden automáticamente por otras clases en el mismo paquete. –

+1

Estoy 100% seguro de que nunca funcionó en ninguna JVM estándar. –

+0

@Michael, no sé por qué, creo que he estado confundiendo con AS3 o algún otro idioma con una súper clase definitiva con un truco similar. –

2

Si está hablando de agregar un rol a todos sus objetos, también consideraría una solución basada en anotaciones. Anotarías tus clases con algo como @Role ("Usuario"). En otra clase puede extraer ese valor de rol y usarlo.

creo que necesitaría una anotación con la retención tiempo de ejecución y se puede comprobar, en tiempo de ejecución, si la anotación está presente mediante la reflexión y conseguir que la anotación utilizando getAnnotation. Siento que esto sería mucho más limpio que extender todas tus clases automáticamente.

Creo que hay algunos marcos que usan exactamente tal solución, por lo que debería haber un código de ejemplo en alguna parte.

1

Lo que realmente quieres hacer es monkey patching, es decir, cambiar el comportamiento de las clases existentes sin modificar su código.

Desafortunadamente, Java no es compatible con esto, ni cosas como mixins que podrían usarse alternativamente. Entonces, a menos que esté dispuesto a cambiar a un lenguaje más dinámico como Groovy, tendrá que vivir con soluciones menos elegantes como la composición.

+0

No necesita necesariamente un lenguaje de tipado dinámico como Groovy o Ruby para aplicar parches o mezclas de mono: algunos lenguajes estáticos, por ejemplo Scala, también son compatibles con mixins, y puede hacer algo parecido a parche de mono en Scala con el " proxeneta de mi biblioteca "patrón. – Jesper

Cuestiones relacionadas