views:

269

answers:

6

Hello, I'm writing (well, completing) an "extension" of Java which will help role programming.
I translate my code to Java code with javacc. My compilers add to every declared class some code. Here's an example to be clearer:

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

It adds Implements.. and the necessary methods to EVERY SINGLE CLASS you declare. Quite rough, isnt'it?

It will be better if I write my methods in one class and all class extends that.. but.. if class already extends another class (just like the example)?

I don't want to create a sort of wrapper that manage roles because i don't want that the programmer has to know much more than Java, few new reserved words and their use.

My idea was to extends java.lang.Object.. but you can't. (right?)
Other ideas?

I'm new here, but I follow this site so thank you for reading and all the answers you give! (I apologize for english, I'm italian)

+3  A: 
  • you can extend Object - every class extends it.
  • you seem to need something like multiple inheritance - there isn't such a thing in Java
  • if you want to add functionality, use object composition. I.e.,

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

And then all of the methods are placed in the RoleHandler

Bozho
When i said "extends Object" I thought to create a super class of Object, that wasn't the right term, sorry. Anyway your answer is useful, i will check if is the solution. Thank you. Fabio F.
Fabio F.
wait, I think he's talkink about extending the Object class, adding functionality to ALL objects
seanizer
+2  A: 

You should consider using composition rather than inheritence to solve this problem; that way you can provide the functionality you need without using up your "one-shot" at inheritence.

For example, the JDK provides a class PropertyChangeSupport, which can be used to manage PropertyChangeListeners and the firing of PropertyChangeEvents. In situations where you wish to write a class that fires PropertyChangeEvents you could embed a PropertyChangeSupport instance variable and delegate all method calls to that. This avoids the need for inheritence and means you can supplement an existing class hierarchy with new functionality.

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);
  }
}
Adamski
+1  A: 

If you are doing what you are doing, then inheritance is probably not the correct idiom. You may want to consider the decorator pattern, whereby you construct a class that takes as its parameter some other class with less functionality, and adds some additional functionality to it, delegating to the existing class for functionality that already exists. If the implementation is common to many of your decorators, you may want to consider putting that functionality in class that can be shared and to which you can delegate for all your decorators. Depending on what you need, double-dispatch or reflection may be appropriate in order to make similar but not quite the same decorators for a large variety of classes.

Also, as has been pointed out in the comments, String is declared "final" and, therefore, cannot be extended. So, you should really consider a solution whereby you delegate/decorate objects. For example, you might have some object that wraps a string and provides access to the string via getString() or toString(), but then adds the additional functionality on top of the String class.

If you just want to associate some objects with additional attributes, use a Map (e.g. HashMap).

Michael Aaron Safyan
1) There is no such thing as a "top-level package". 2) Classes named "Object" are most definitely *not* automatically extended by other classes in the same package.
Michael Borgwardt
I'm 100% sure that never worked in any standard-compliant JVM.
Michael Borgwardt
@Michael, nevermind, I think I may have been confusing with AS3 or some other language with an ultimate super class with a similar hack.
Michael Aaron Safyan
+6  A: 

If it is only like a "research" project in which you want to explore how such extension would work, you could provide your own implementation of the Object class. Simply copy the existing object implementation, add your setRole method etc, and give -Xbootclasspath:.:/usr/lib/jvm/java-6-sun/jre/lib/rt.jar as parameter to the java command. (I will look for api-classes in . before looking in the real rt.jar.)

aioobe
I'm trying to implement your solution: adding the Object file in the directory (.) java/lang/Object.java modified with my methods. It compile (so it finds the methods) but when I try to execute i get NoSuchMethodError.. I used -Xbootclasspath and -classpath with the same result. (Javac works even without that!)
Fabio F.
you should add the Object.class, not in the `.` directory, but in the `./java/lang` directory.
aioobe
Stupid english.. i've done that i've copied the java/lang in . It compiles but not execute. Sorry..
Fabio F.
You should not copy the `java/lang` into `.`. You should place your object.class file in a directory `java/lang` in your current directory. Read my last comment again :) Also, make sure the implementation starts with `package java.lang;`
aioobe
We don't understand each other. I've copied the directory, the directory, not the content. In my . there is java which contains lang which contains Object.java and Object.class (that is created when i compile). If i put in my file (the one i try to compile) package java.lang; it says NoClassDefFoundError. Thank you for your patience.
Fabio F.
+2  A: 

If you're talking about adding a role to all your objects I would also consider an annotation-based solution. You'd annotate your classes with something like @Role("User"). In another class you can extract that role value and use it.

I think it would need an annotation with runtime retention and you can check, run-time, whether the annotation is present using reflection and get that annotation using getAnnotation. I feel that this would be a lot cleaner than extending all your classes automatically.

I believe there are some frameworks which use exactly such a solution, so there should be example code somewhere.

extraneon
+1  A: 

What you really want to do would be monkey patching, i.e. changing the behaviour of existing classes without modifying their code.

Unfortunately, Java does not support this, nor things like mixins that might be used alternatively. So unless you're willing to switch to a more dynamic language like Groovy, you'll have to live with less elegant solutions like composition.

Michael Borgwardt
You don't necessarily need a dynamically typed language such as Groovy or Ruby to do monkey patching or mixins - some static languages, for example Scala, also support mixins, and you can do something that looks like monkey patching in Scala with the "pimp my library" pattern.
Jesper