I want to implement method chaining like in those questions:
Best practice to implement Scala trait which supports method chaining ;
Scala DSL: method chaining with parameterless methods
However, I want that once a "property" has been used, it cannot be used anymore. For example lets assume that I have a class "Myclass" for which I want to allow the use of definition "foo" and definition "bar" at most once and I don't care about the final return type. Thus:
val c = new Myclass
c foo //ok !
c foo bar // ok!
c foo foo // refuse to compile
c foo bar foo //refuse to compile
I'm struggling with this problem for a while and my vision starts becoming fuzzy! I tried to use implicit classes, however, whether they need to parse objects that has not used the associated property, and I can't find how, whether they need to "consume" the property by removing it from the object available property, and, again, I can't find how.
I'm currently searching in the reflection API, but it is still a little obscure for me.
Help would be appreciated! =)
Method chaining, also known as named parameter idiom, is a common syntax for invoking multiple method calls in object-oriented programming languages. Each method returns an object, allowing the calls to be chained together in a single statement without requiring variables to store the intermediate results.
The drawback to self-referential method chaining is that you communicate that multiple method calls are required to do something, and that each call builds off the last. If this is not true, then method chaining could be communicating the wrong thing to other programmers.
Method chaining is the mechanism of calling a method on another method of the same object. This ensures a cleaner and readable code. Method chaining uses this keyword in the object's class to access its methods. In javascript, the this keyword refers to the current object in which it is called.
In method chaining, we call separate methods of a single object like a chain without assigning the same object multiple times by assignment operators. Method chaining works well when we use asynchronous functions with promises. Sometimes we take data from a network which does not synchronous to our code.
See Phantom Types In Haskell and Scala by James Iry.
You could also use type-safe builder pattern:
trait TTrue
trait TFalse
@annotation.implicitNotFound(msg = "Cannot call same method twice.")
sealed abstract class =^=[From, To]
object =^= {
private val singleton_=^= = new =^=[Any, Any]{}
implicit def tpEquals[A]: A =^= A = singleton_=^=.asInstanceOf[A =^= A]
}
class Myclass[TFoo, TBar, TBuz] private(){
def foo(implicit e: TFoo =^= TFalse) = new Myclass[TTrue, TBar, TBuz]
def bar(implicit e: TBar =^= TFalse) = new Myclass[TFoo, TTrue, TBuz]
def buz(implicit e: TBuz =^= TFalse) = new Myclass[TFoo, TBar, TTrue]
}
object Myclass{
def apply() = new Myclass[TFalse, TFalse, TFalse]
}
to be used like this
scala> Myclass().foo.bar.buz
res0: Myclass[TTrue,TTrue,TTrue] = Myclass@12ac706a
scala> Myclass().bar.buz.foo
res1: Myclass[TTrue,TTrue,TTrue] = Myclass@1e69dff6
scala> Myclass().foo.buz.foo
<console>:12: error: Cannot call same method twice.
Myclass().foo.buz.foo
^
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With