-- 1. In your example, I would not use the summary(o) version, since this is not a very object-oriented programming style. When you call o.summary (you can remove the brackets since it has no side effects), you request the summary o property. When you call summary(o) you pass o method that computes the summary o . I think the first approach is more enjoyable :).
I did not use scheduling of the structural type, but I assume that it is best suited (on a large system) for the case when you have to write an interface just because one method needs a type that has a specific method, Sometimes creating this interface and forcing clients its implementation may be inconvenient. Sometimes you want to use a client defined in another API that matches your interface but does not explicitly implement it. So, in my opinion, scheduling a structural type is a good way to make an adapter template implicit (it saves on a template, yay!).
-- 2. Apparently, if you call summary(o) and o has an ObjectType , it calls the summary(o: ObjectType) (which makes sense). If you call summary(bar) , in which bar does not matter ObjectType , two things can happen. The call compiles if bar has the summary() method of the right signature and name or otherwise, the call does not compile.
Example:
scala> case class ObjectType(summary: Double) defined class ObjectType scala> val o = ObjectType(1.2) o: ObjectType = ObjectType(1.2) scala> object Test { | def summary(o: ObjectType) { println("1") } | def summary(o: { def summary: Double}) { println("2")} | } defined module Test scala> Test.summary(o) 1
Unfortunately, something like the following does not compile due to type erasure:
scala> object Test{ | def foo(a: {def a: Int}) { println("A") } | def foo(b: {def b: Int}) { println("B") } | } :6: error: double definition: method foo:(AnyRef{def b(): Int})Unit and method foo:(AnyRef{def a(): Int})Unit at line 5 have same type after erasure: (java.lang.Object)Unit def foo(b: {def b: Int}) { println("B") }
-- 3. In a certain sense, scheduling of a structural type is more dynamic than general methods, and also serves a different purpose. In the general method, you can say either: a. I want something like; b. I want something of type that is a subtype of A; with. I'll take something that is supertype B; e. I'll take something that has an implicit type C conversion. All of them are much more strict than just "I want a type that has the foo method with the correct signature." In addition, scheduling of a structural type uses reflection, since they are implemented by erasing the type.
I donβt know much about multimethods, but looking at the Wikipedia article , it seems that dots can be achieved in Scala using a pattern matching. Example:
def collide(a: Collider, b: Collider) = (a, b) match { case (asteroid: Asteroid, spaceship: Spaceship) => // ... case (asteroid1: Asteroid, asteroid2: Asteroid) => // ... ...
Again, you can use a structural type dispatcher - def collide(a: {def processCollision()}) , but it depends on the design solution (and I would create an interface in this example).
-- Flaviu Cipcigan