apply
is defined on Function1
, the parent class of PartialFunction
(Note that A => B
is syntax sugar for Function1[A, B]
). isDefinedAt
is defined directly on the PartialFunction
trait. Note that both are abstract. If you write a function, you're responsible for determining what apply
does. If you write a partial function, you're responsible for determining where it's defined.
isDefinedAt
will often get magicked away by the compiler if you use partial function syntax. So if we write
val f: PartialFunction[Option[Int], Int] = { case Some(x) => x }
Then we can do
f.isDefinedAt(None) // false
f.isDefinedAt(Some(1)) // true
EDIT: Based on your comment, you're confused by PartialFunction.this.apply
. Note the context in which this is executed.
new PartialFunction[A1, B1] {
def isDefinedAt(x: A1): Boolean =
PartialFunction.this.isDefinedAt(x) || that.isDefinedAt(x)
def apply(x: A1): B1 =
if (PartialFunction.this.isDefinedAt(x)) PartialFunction.this.apply(x)
else that.apply(x)
}
We're inside of a new anonymous object. this
refers to that anonymous object. If we implemented apply
in terms of this.apply
, then it would be infinite recursion. Think of PartialFunction.this
as being kind of like super
, but rather than calling the superclass method, we're calling the concrete class method from inside of an anonymous instance.