Patterns as such have nothing to do with objects or encapsulation. The whole semantics of a Pattern is given by the unapply-method of the object of that name. This has to be a function from some type you want to match on to an optional. It matches, if the apply function returns something. You can match on any type and return value you want.
In your case your unapply-method takes an integer and returns an other integer if successful. It does not matter, that the object Twice also has an apply method and it does not matter, where the integer came from.
You can even remove the apply-method an still do this
8 match { case Twice(n) => println(n) }
it will work as well.
The compiler just transforms this into something like
val temp = Twice.unapply(8) if(temp.isDefined) { val n = temp.get println(n) }
(Probably something more complicated as it has to be more general to support all features of patterns.)