Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] ITD syntax

I'm glad for this discussion because it's helped me in refining how I think this would work best.  So lets call the object containing the default implementation the source and the object inheriting them will be the target (if there is more proper terminology please let me know).  I'm all for using a declare type statement to define which targets inherit from a source and I think that having the source be a POJO would be great.  It's clean and it's simple.  I think that the declare statement should define which interface the source provides implementations for and that only methods within that interface should show up in the target.  As far as implementation goes, I think the target should hold a reference to the source that it simply delegates calls to.  So basically what we have here is the delegation pattern made easy.  It's standard Java faux multiple inheritance without all the hassle.  The only thing that would leave unresolved is how calls to "this" are handled since we don't want a situation like this:

public interface DoSomething{

public boolean canDoSomething();

public void doIt();

}

public class DoSomethingImpl implements DoSomething{

public boolean canDoSomething(){
//default to no
return false;
}

public void doIt(){
if(this.canDoSomething()){
...do it...
} else{
throw new SecurityException("You can't do that");
}
}

//my new made up syntax containing the interface type
declare delegate: DoSomething+ to DoSomethingImpl implementing DoSomething;

}

public class Doer implements DoSomething{

public boolean canDoSomething(){
//if you have access to this object, you can do something
return true;
}

}

The problem here is that in typical delegation Doer delegates to an instance of DoSomethingImpl, which then calls it's own canDoSomething() method rather than the "overridden" one within Doer itself.  I see 2 solutions to this problem.  a) AJ rewrites all calls to this.[delegatedMethod] as a call to the corresponding method within the target. b) All source classes may have a constructor that takes an object of the interface type that it provides defaults for.  That's confusing so in other words DoSomethingImpl becomes:

public class DoSomethingImpl implements DoSomething{

private DoSomething target = this;

public DoSomethingImpl();

public DoSomethingImpl(DoSomething target){
this.target = target;
}

public boolean canDoSomething(){
//default to no
return false;
}

public void doIt(){
if(target.canDoSomething()){
...do it...
} else{
throw new SecurityException("You can't do that");
}
}

declare delegate: DoSomething+ to DoSomethingImpl implementing DoSomething;

}

Now if the target defines it's own implementation of canDoSomething() that will be called, otherwise the generated delegate will be called which will just fall back to the default implementation.  Of course, the no arg constructor and defaulting of the target field to "this" is not necessary but it would allow the class to be used in a regular single inheritance hierarchy as well.  In that situation it would just call itself.  I've set up object hierarchies like this before and in my experience it does work, it just sucks to manually put the instance references into each object, generate the delegate methods, keep them up to date if the interface changes, etc, etc.  Anybody agree, disagree?

On Dec 4, 2008, at 1:33 PM, Simone Gianni wrote:

Hi Dave,
technically speaking there is not much a difference, it's just what the
user perceives. In a language that supports mixins, you can write
"Minotaur = Person + Bull" you are not adding methods to Person to
support Bull functions or method to Bull to add Person functions. In
Java this is not possible (well, there are patterns,
Minotaur.getHumanPart() and Minotaur.getBullPart() ), there will always
be a "main" class, and a number of "added" methods.

What you can obtain is more or less the same, but the way the user will
perceive it is not the same. In the current ITD syntax it is absolutely
clear what you are adding to which classes. In your proposal it is still
clear. In the Ramnivas proposal it somehow fades away, making me feel we
could be giving the user a wrong perception ... but I may absolutely be
proven wrong! :D

Technically speaking it does not change that much, and I like a lot both
proposals, I'm just thinking of how this would change how the users
feels what he is doing since this seems to be one of the biggest
problems people have when considering aspects (see the in-famous
Wikipedia entry).

Simone

Dave Whittaker wrote:
Simone,

I think I see what you are saying, but can you just clarify the
difference between an ITD and a mixin for me?  I had always thought of
them as being interchangeable, but I'm admittedly more familiar with
the use of aspects than the theory.

I think that you are correct that keeping fields "private to the
aspect" should not be violated, but couldn't this be implemented using
the standard delegation pattern that most people seem to recommend for
implementing multiple inheritance in Java?  The declare statement
could cause any advised class to hold a reference to the class that
contains the default implementation and then automatically create the
delegate methods for you as per the interface.  Since only the methods
in the interface would be added even if the class containing the
default implementation were to implement other methods or extend other
classes, the user would not be aware (which i think solves your other
problem).  I guess this would be more of a complement to ITDs than an
alternative implementation since it would not allow the creation of
methods that aren't contained in the interface but personally, I would
see that as a positive thing for most of my own use cases.

What this basically boils down to for me is that the Java powers that
be have dictated, no multiple inheritance unless it's done with
interfaces and delegation, which works but a) it's an enormous pain to
create the delegate methods and then keep them in sync for every
targeted class and b) references to "this" inside a class that's being
delegated to don't do what they'd do in a situation where true
inheritance was involved.  If AJ could solve both of those issues and
make it as easy as a declare statement, I'd imagine I'm not the only
person that would be useful to....  What do you all think?

On Dec 4, 2008, at 12:22 PM, Simone Gianni wrote:

Hi Ramnivas and Dave,
yes, I also liked the proposal, in fact I also find the ITD syntax a bit
too verbose.

Ramnivas, your proposal moves from ITD to something near mixins, which I
really like :). Anyway, that class could be every class, and that bring
a number of problems, cause it could extend another class, and since
Java does not support multiple inheritance we should not give the user
the feeling that it is happening. Also, the fact that a ITD field is
private "to the aspect"is a very good feature, I already have more than
one aspect declaring a "inited" boolean field, each aspect uses it to
mark a certain instance inited regarding its own concern. I see not much
a technical problem in obtaining the same behavior with your proposal,
but again a problem from a user POV.

The direction seems correct to me, but some boundaries must be defined
to give the user the proper feeling of what they are doing.

Simone


Ramnivas Laddad wrote:
I like this proposal.

Here is an alternative syntax suggestion that
- addresses Dave's use case
- addresses a use case that is easy to implement in @AspectJ but not
in code style
- avoids new keywords

public aspect ITDAspect{

  /* don't have define the class here, don't need to make it private;
      but defining it that way matches Dave's example
 */
  private static class ITDDefaultImpl {
      private String string;

      public String getString(){
          return string;
      }

      public void setString(String string){
          this.string = string;
      }
  }

  /* declare that ITDInterface should be introduced with
      all fields and methods in ITDDefaultImpl
      Not sure about the choice of using "extends"
      (trying to avoid new keyword)
      Alternatives: declare implements? declare default?
  */
  declare extends: ITDInterface, ITDDefaultImpl;
}

This makes a common use case implemented by the following @AspectJ
snippet available in the code style syntax. Essentially, I get to
reuse the implementation available from an existing class.

@DeclareParents(value="com.myco.domain.*",
                           defaultImpl= ITDDefaultImpl.class)
ITDInterface something;

How does this sound?

-Ramnivas

On Wed, Dec 3, 2008 at 9:40 PM, Andy Clement
<andrew.clement@xxxxxxxxx> wrote:

I could be wrong but I think I recall someone talking about something
like this a while ago - possibly Ramnivas.  Although having just
trawled through our enhancement requests, I only found this:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=240011 which is about
saving typing but isn't quite the same thing.  What you propose is
interesting, what do others think?

cheers,
Andy.

2008/12/3 Dave Whittaker <dave@xxxxxxxxxx>

I've been wondering recently.... is there a reason that ITDs are
defined the way they are?  I don't know how others tend to use
them, but for me I'm pretty likely to have an aspect that contains
ITD fields and methods that apply to a single interface within a
given aspect.  This makes me wonder why we have a syntax like:

public aspect ITDAspect{

     private String ITDInterface.string;

     public String ITDInterface.getString(){
             return string;
     }

     public void ITDInterface.setString(String string){
             this.string = string;
     }

}

Instead of:

public aspect ITDAspect{

     intertype(ITDInterface){


             private String string;

             public String getString(){
                     return string;
             }

             public void setString(String string){
                     this.string = string;
             }

     }
}

Or something similar.  Something that involved less typing,
consolidated code that is defined for another type and looked more
like plain java code (not to mention more like other AJ
definitions in this case....).  At the very least it would allow
for something that I've wanted many times: cut and paste between
classes and ITDs without having to post process with some sort of
wacky regex.  Am I missing a reason why it's desirable or even
necessary to type out the full interface name on each line?
_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users

_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users


_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users



--Simone Gianni            CEO Semeru s.r.l.           Apache Committer
http://www.simonegianni.it/

_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users

_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users


--
Simone Gianni            CEO Semeru s.r.l.           Apache Committer
http://www.simonegianni.it/

_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users


Back to the top