Advertisement
Guest User

LockAndKey.scala

a guest
Dec 5th, 2016
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 2.20 KB | None | 0 0
  1.  
  2. import scala.language.existentials
  3.  
  4. class KeyShape {}
  5.  
  6. abstract class Key {
  7.   def ref(): KeyShape
  8. }
  9.  
  10. abstract class Lock[T] {
  11.   type Corresponding <: Key
  12.   def ref: KeyShape
  13.   def unlock(key: Corresponding): T
  14.   def tryUnlock(key: Key): Option[T] = {
  15.     if (key.ref == this.ref)
  16.       Some(unlock(key.asInstanceOf[Corresponding]))
  17.     else
  18.       None
  19.   }
  20. }
  21.  
  22. class LockAndKey[T] {
  23.   private val _ref = new KeyShape
  24.  
  25.   final class MatchingKey() extends Key {
  26.     def ref = _ref
  27.   }
  28.  
  29.   class MatchingLock(private val inner: T) extends Lock[T] {
  30.     type Corresponding = MatchingKey
  31.     def ref = _ref
  32.     def unlock(key: Corresponding): T = {
  33.       if (key == null) // For security reasons, check and make sure null hasn't slipped in
  34.         throw new NullPointerException
  35.       inner
  36.     }
  37.   }
  38.  
  39.   def producePair(inner: T): (MatchingKey, MatchingLock) = (new MatchingKey, new MatchingLock(inner))
  40.  
  41. }
  42.  
  43. object LockAndKey extends App {
  44.  
  45.   // Each lock hides an object which can only be accessed using the corresponding key.
  46.  
  47.   val(key1, lock1) = (new LockAndKey).producePair(7)
  48.   val(key2, lock2) = (new LockAndKey).producePair("ABC")
  49.   val(key3, lock3) = (new LockAndKey).producePair(10)
  50.  
  51.   // If the type system can prove that the key and lock match, you don't have to go through an Option[T]
  52.   println(lock1.unlock(key1))
  53.   println(lock2.unlock(key2))
  54.   println(lock3.unlock(key3))
  55.  
  56.   // This line does not even compile, since the lock and key don't line up
  57.   // println(lock1.unlock(key3))
  58.  
  59.   // Attempting to pass null is illegal
  60.   // println(lock3.unlock(null))
  61.  
  62.   // If the type system isn't certain, you can use tryUnlock, which returns an Option[T]
  63.   println(lock1.tryUnlock(key1)) // Matching, so okay
  64.   println(lock2.tryUnlock(key1)) // Returns None
  65.  
  66.   // This one will typecheck but will crash at runtime since the types don't line up.
  67.   // println(lock3.tryUnlock(new Key { override def ref() = lock3.ref; }));
  68.  
  69.   // We can't force the types to line up using anonymous subclasses either, since MatchingKey
  70.   // is declared to be final.
  71.   // val breaker = new LockAndKey
  72.   // println(lock3.tryUnlock(new breaker.MatchingKey { override def ref() = lock3.ref; }))
  73.  
  74. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement