John
John

Reputation: 816

Scala reduce duplicate code from inheritance

class CharacterFilter extends Filter[Character] {
    def _name(n: String) = { data = data.filter(c => c.name == n) }
}
class NPCFilter extends CharacterFilter {
    def name(n: String) = { _name(n); this }
}
class PlayerFilter extends CharacterFilter {
    def name(n: String) = { _name(n); this }
}

I'm building some classes that filter through data. NPCFilter and PlayerFilter should share methods from CharacterFilter. However, I want each filter to return themselves at the end so that I can chain functions like this: .name("John").age(18).race(WHITE)

At first I tried this, but it doesn't give the result I want, because I am left with a CharacterFilter after calling name instead of a NPCFilter or PlayerFilter as desired.

class CharacterFilter extends Filter[Character] {
    def name(n: String) = { data = data.filter(c => c.name == n); this }
}
class NPCFilter extends CharacterFilter {
}
class PlayerFilter extends CharacterFilter {
}

So my first example works exactly how I want it to, but it feels repetitive (especially once I add more functions). Is there a way to make it more concise?

Upvotes: 1

Views: 212

Answers (1)

Didier Dupont
Didier Dupont

Reputation: 29538

For this particular case where you return this, there is a direct support :

def f(....) : this.type =  ....

Writing that, this is the only valid return value, and the compiler will type it just as it typed the target of the call to f.

Short of that particular case, if your return type is somewhat tied to the type of the target, but not necessarily this, you need a type member, or a generic, such as

abstract class A[T <: A[T]] {self: T =>
   def f(....): T
}

class B extends A[B] { ... }

Upvotes: 4

Related Questions