Dear all,
Just imagine, suppose we have two traits `spots-trait` and `stripes-trait`, they are developed independently.
These two traits depend on a "private" method `helper` respectively.
See following code:
```
(define spots-trait
(trait
(define/public (helper)
(println "spots-trait helper"))
(define/public (eat/spots)
(println "spots-trait eat/spots")
(helper))
))
(define stripes-trait
(trait
(define/public (helper)
(println "stripes-trait helper"))
(define/public (eat/stripes)
(println "stripes-trait eat/spots")
(helper))
))
```
Now I want to define the 3rd trait (called `spots+stripes-trait`), something like:
```
(define spots+stripes-trait
(trait-sum spots-trait stripes-trait))
```
But this is impossible because there is a name colliding (the`helper` method).
One workaround to this problem is "renaming":
```
(define spots+stripes-trait
(trait-sum
(trait-rename spots-trait helper helper/spots)
(trait-rename stripes-trait helper helper/stripes)))
```
This works.
But is this a good way? (It looks not very "hygienic")
Note that the `helper` is just a "private" method, it should not be visible to its user.
PS: It seems that Racket does not support private members for traits. Although I don't think "private members" is a good idea because private members are not friendly to unit-testing.
An alternative way is moving the private `helper` method to a different trait, splitting the original responsibilities across multiple traits leading to simpler, better designs.
See following code:
```
(define spots-helper-trait
(trait
(define/public (helper)
(println "spots-helper-trait helper"))
))
(define spots-core-trait
(trait
(inherit helper)
(define/public (eat/spots)
(println "spots-core-trait eat/spots")
(helper))
))
(define stripes-helper-trait
(trait
(define/public (helper)
(println "stripes-trait helper"))
))
(define stripes-core-trait
(trait
(inherit helper)
(define/public (eat/stripes)
(println "stripes-core-trait eat/spots")
(helper))
))
```
Now I can redefine `spots-trait` and `stripes-trait`.
My attempt is `trait-sum` the `spots-core-trait` and `spots-helper-trait` first, and then "hide" the `helper`, something like:
```
(define spots-trait
(trait-hide ;; <-- attempt
to hide `helper` method (Not real Racket)
(trait-sum spots-core-trait spots-helper-trait)
helper))
(define stripes-trait
(trait-hide ;;
<--
attempt
to
hide `helper` method
(Not real Racket)
(trait-sum stripes-core-trait stripes-helper-trait)
helper))
(define spots+stripes-trait
(trait-sum spots-trait stripes-trait))
```
Is this possible in Racket?
The advantage of
"hiding"
is that
1. The `spots-trait` now only exposes its interface `eat/spots
`, we can easily reuse it in other traits without worrying about name
colliding (the name `helper` is very commonly used, imo)
.
2. Compared with the "renaming" solution, "hiding"
looks more "hygienic", because it
can avoid further name colliding.
PS: I admit this example may be a bit weird, but you can think of "spots" and "stripes" as some sort of service traits.
Thanks.
Best regards,
Siyuan Chen