Yes, Tracks has other methods that I did not show.
I just did a quick test of export, and it seems to do exactly what I asked for if I just add
Nice! I’ll try not to abuse it.
By the way, one reason this feature is significant to me is that it allows me to essentially replace all occurrences of Vector[Track] with Tracks in my code without making any other changes. That not only eliminates work, but it also reduces the chances of an error.
After working with it a bit, I now realize that “export” does not quite do exactly what I wanted, but it’s still a step forward.
For basic Vector methods like “isEmpty”, “length”, etc., it does exactly what I want. But for methods like “take”, “drop”, etc., it returns a Vector[Track] rather than a Tracks instance. That should have been obvious, I guess.
If your other methods do not require additional fields, i.e. the Vector[Track] is the only thing stored in that class, you could maybe use extension methods instead? (as you can use export, I assume you’re using dotty)
The decorator pattern usually is about extending the implementation of some well-defined, closed API (Component in the Wikipedia page), rather than just exposing any method available on a wrapped object. And for this use case Scala provides the stackable traits feature/pattern.
I thought your suggestion to use “extension” might be the answer. However, I tried it and was disappointed.
The problem is that the namespace is apparently shared with other Vector extensions. So if I have a Tracks = Vector[Track] and Things = Vector[Thing] (made up name), I can’t use the same method name in the two of them. I did not expect that, since I thought that Vector[Track] and Vector[Thing] were two different types. I could put them inside companion objects, but then I have to use imports or qualified names, which is not as elegant.
Also, I wanted a toString method, and for some reason the compiler wouldn’t let me add that.
Extension seems like a nice idea, but I had other problems with it as well when I tried to convert some some of my implicit classes to extensions. I certainly hope implicit classes are not going away unless or until extension can do everything they can do.
scala> class A; class B
// defined class A
// defined class B
scala> extension (as: Vector[A]) def foo = 3
def foo(as: Vector[A]): Int
scala> extension (bs: Vector[B]) def foo = "bar"
def foo(bs: Vector[B]): String
scala> Vector(new B).foo
val res0: String = bar
scala> Vector(new A).foo
1 |Vector(new A).foo
|value foo is not a member of Vector[A].
|An extension method was tried, but could not be fully constructed:
| foo(Vector.apply[A]([new A() : A]:A*))
I’m curious if this is considered to be working-as-designed, or whether it could be changed.
Although “extension” has problems as noted above, I am finding that implicit classes can be used to solve this problem fairly nicely. (But it requires the use of the “implicit” keyword, which might freak some people out!)
That leaves me wondering what the relationship is between extension and implicit classes. Although extension apparently cannot be used to add data fields, it seems to serve the same purpose as implicit classes otherwise.
Is extension intended to eventually replace implicit classes? If so, it still needs some work.