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
<[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]>
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
[email protected]
https://dev.eclipse.org/mailman/listinfo/aspectj-users
_______________________________________________
aspectj-users mailing list
[email protected]
https://dev.eclipse.org/mailman/listinfo/aspectj-users
_______________________________________________
aspectj-users mailing list
[email protected]
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
[email protected]
https://dev.eclipse.org/mailman/listinfo/aspectj-users
_______________________________________________
aspectj-users mailing list
[email protected]
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
[email protected]
https://dev.eclipse.org/mailman/listinfo/aspectj-users
_______________________________________________
aspectj-users mailing list
[email protected]
https://dev.eclipse.org/mailman/listinfo/aspectj-users