- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
When to use self reference or composition?
Fri, 2011-08-19, 11:04
Hello,
have a look to the following code snippet:
trait T { def y = println("hello")}
class A {
self: T =>
def x = y
}
abstract class B {
val self: T
def x = self.y
}
val a = new A with T
val b = new B with T {
val self = this
}
a.x
b.x
Class A and B have a reference to trait T, A has a self reference and B
is using composition.
I see only two differences here: The first is in creating new objects
and the second in accessing T.
In B there is more syntactic sugar, I don't need to explicitly access
reference self and I don't need to bind the variable.
Are there another differences and are there some situations in which one
should preferred instead of the other?
Thanks
Antoras
Sun, 2011-08-28, 11:27
#2
Re: Re: When to use self reference or composition?
Thanks for your response. Your example can also be used with composition:
class Node {...}
trait Box {
val self: Node; ...}
class ViewableNode extends Node with Box {val self = this; ...}
There is no difference with exception of the syntactic clues.
Btw., some days ago I asked this question on StackOverflow[1].
[1]
http://stackoverflow.com/questions/7177334/when-to-use-self-references-o...
On 27.08.2011 20:59, Ken McDonald wrote:
> Well, I'd say there are big differences.
>
> The most significant is that in B, you do not have a _guarantee_ that
> your object of type T is in fact the same object as your object of
> type A; that depends entirely on the assignment your making, which is
> a potential point of error.
>
> As well, not being able to say "b.y" can get pretty annoying once your
> classes start becoming large and complex.
>
> Finally, the "direction" in which you're using self-typing is opposite
> to the direction I typically use it (not that I'm the last word on the
> matter). As an example, I currently have some code that defines a Node
> class, which is a structural type--it is part of a tree. I also have a
> trait called a Box, which draws things onscreen, and can be inherited
> by certain types of Nodes that have a graphical representation.
> However, a Box, in order to do its work, needs access to data in the
> node. So, to give a simplified representation:
>
> class Node {...}
>
> trait Box {
> this: Node => ...}
>
> class ViewableNode extends Node with Box {...}
>
> In other words, self typing is (here) used to indicated that a trait
> will only ever be inherited from by a particular type--which enables
> the trait to use the methods and data of that, type, which would not
> otherwise be possible.
>
> Hope this helps,
> Ken
Tue, 2011-08-30, 23:07
#3
Re: Re: When to use self reference or composition?
You can do it that way of course, but why would you choose a more confusing, more verbose, and more confusing (especially in the Box code that accesses Node) way of doing things? Plus the fact that you _still_ have no absolute guarantee that Box.self is the same Node Box is inherited by?
Like many programming features, self-typing is not only aimed at allowing you to do things that would otherwise be impossible (I suspect someone more talented than I could come up with such examples), but also to make coding simpler, more obvious, and more robust.
Cheers,Ken
Like many programming features, self-typing is not only aimed at allowing you to do things that would otherwise be impossible (I suspect someone more talented than I could come up with such examples), but also to make coding simpler, more obvious, and more robust.
Cheers,Ken
The most significant is that in B, you do not have a _guarantee_ that your object of type T is in fact the same object as your object of type A; that depends entirely on the assignment your making, which is a potential point of error.
As well, not being able to say "b.y" can get pretty annoying once your classes start becoming large and complex.
Finally, the "direction" in which you're using self-typing is opposite to the direction I typically use it (not that I'm the last word on the matter). As an example, I currently have some code that defines a Node class, which is a structural type--it is part of a tree. I also have a trait called a Box, which draws things onscreen, and can be inherited by certain types of Nodes that have a graphical representation. However, a Box, in order to do its work, needs access to data in the node. So, to give a simplified representation:
class Node {...}
trait Box { this: Node => ...}
class ViewableNode extends Node with Box {...}
In other words, self typing is (here) used to indicated that a trait will only ever be inherited from by a particular type--which enables the trait to use the methods and data of that, type, which would not otherwise be possible.
Hope this helps,Ken