Wednesday, December 7, 2011

Learning Scala : upper bound "<:" and lower bound ">:" for laypeople

Authored by Win Myo Htet

Scala has a very rich type system. One aspect of the type system is variance, which is annotated by "+" or "-" or " " (e.g. List[+A]). From that, we also have lower bound and upper bound. We are not going to get into the detail of it. We will only try to understand it from the object oriented analogy.  Generally, lower bound, ">:", can be seen as [Parent >: Child] format and upper bound, "<:", as [Child<:Parent]. They are there for the proper usage of the Scala generic. A code snippet is worth a thousand words. So, here is the code:

abstract class Animal (animalType:String)

class HasFourLegs(animalType:String) extends Animal(animalType){
  def move=println(this+" walking on four legs")

class HasTwoLegs(animalType:String) extends Animal(animalType){
  def move=println(this+" walking on Two legs")

case class Dog(animalType:String) extends HasFourLegs(animalType)
case class Ostrich(animalType:String) extends HasTwoLegs(animalType)

  def moveOn4legs[T<:HasFourLegs](animal:T)=  animal.move
  val dog = Dog("dog")
  val ostrich=Ostrich("ostrich")
  error: inferred type arguments [this.Ostrich] do not conform to method moveOn4legs's type parameter bounds [T <: this.HasFourLegs]
class AnimalMovement [+T]{
  def movement[U>:T](animal:U)=println(animal+" walking on Two legs!!!")

  val moveLikeTwoLegs=new AnimalMovement[HasTwoLegs]()

We have two kinds of animals: 4 legs and 2 legs. From there, we have a Dog and an Ostrich. We then have a method, moveOn4legs, with upper bound parameterized as moveOn4legs[T<:HasFourLegs], thus restricting the  paramter type to be the Child of HasFourLegs class. We can only use this method for Dog which extends HasFourLegs. We get compile time error when we use Ostrich which does not extends HasFourLegs.

Now we get to the AnimalMovement class with [+T], which is covariance. ([-T] is contravariance and [T] is invariant). Inside it, we have a parameterized method with lower bound,  movement[U>:T](animal:U). We create an object, moveLikeTwoLegs, out of it with the type HasTwoLegs. The movement method is then invoked with both dog and ostrich. Here is the output of this whole code snippet.

aunndroid@ubuntu:/host/linux/learning_scala/notes$ scala upper_lower_Bound.scala 
Dog(dog) walking on four legs

Ostrich(ostrich) walking on Two legs!!!
Dog(dog) walking on Two legs!!!

From, the print out of the last two lines, we see that lower bound let us use dog, an object of DOG, which is not a Child of HasTwoLegs but of HasFourLegs, which shares the same Parent Animal.

Of course, proper usage of the terms should be supertype for Parent and subtype for Child but we just want to grasp the concept of upper bound "<:" and lower bound ">:" only.

Authored by Win Myo Htet

1 comment:

  1. Hydraulics additionally offer unparalleled clamping forces of their clamping unit (3-4 tons per square inch!), making them perfect for bigger molds. Injection molding is simply possible due to the plastic injection molding machine. Plastic injection molding machines combine material feeding, melting, injection, and ejection in one condensed area, and allows for the mass production of products. Thermoplastic injection molding machines produce molded plastic parts by converting plastic pellets into molten material, injecting the molten plastic right into a mould, and cooling the plastic material. One half is linked to a movable platen and the other is linked to a stationary platen. As the machine prepares to inject molten Womens Gloves plastic into the mould, the platens close and press the mould halves tightly together.