
int in Java. Set of numbers between Integer.MIN_VALUE and Integer.MAX_VALUE. Operations +, -, *, etc.int short long byte char float double booleannull. (Null type)(String, Int)(String, String) => Int"Hello".println(). String has no such methodString[] words = { "Hello", "World" };
Object[] objs = words; // compiles: Can convert String[] to Object[]
objs[0] = new Watermelon(); // compiles. Can convert Watermelon to Object
// Oops: Now words[0] is a Watermelon!
Causes ArrayStoreException at run-time.
int luckyNumbers[] = { 17, 29 };
double* values = (double*) luckyNumbers; // compiles
double x = values[0]; // may not be a legal floating-point value
NullPointerException, ArrayStoreExceptionval x = "Hello" ... x = new Duck(); ... x.quack()
Variables have no types, but values do. Errors caught at run-time ("Duck typing").
val x = "Hello" // x is inferred to be String
class Pair[T](val first: T, val second: T)
val p1 = new Pair(17, 29) // Pair[Int]
val p2 = new Pair("Hello", "World") // Pair[String]
def firstTwo[T](a : Array[T]) = new Pair(a(0), a(1))
def min[T](p : Pair[T]) = if (p.first < p.second) p.first else p.second
p.first < p.second
is defined—depends on whether T has <
Ordered[T] ensures that t < t2 operator exists for t ∈ Tdef min[T <: Ordered[T]](p : Pair[T]) = if (p.first < p.second) ...
p.first < p.second is validInt is always converted to Scala RichInt, and RichInt <: Ordered[Int]. <% instead of <: if you want to allow conversions
def min[T <% Ordered[T]](p : Pair[T]) = if (p.first < p.second) ...
Student <: Person (i.e. every student is a person). Should an array of students be a subtype of “array of Person objects”?G[S] and G[T]Array[Student] and Array[Person]class List[+T]
Now List[Student] <: List[Person]
G[+T] means that S <: T ⇒ G[S] <: G[T]trait Function1 [-T1, +R]
Function1[Person, String] <: Function1[Student, String]
abstract class GList[+T] {
def isEmpty : Boolean
def head : T
def tail : GList[T]
}
case class GEmpty[T]() extends GList[T] {
override def isEmpty : Boolean = true
override def head = error("No head")
override def tail = error("No tail")
}
case class GNonEmpty[T](hd : T, tl : GList[T]) extends GList[T] {
override def isEmpty : Boolean = false
override def head = hd
override def tail = tl
}
scala> val foo = GNonEmpty("foo", GEmpty[String]())
foo: GNonEmpty[String] = GNonEmpty(foo,GEmpty())
scala> val bar = GNonEmpty(1, foo)
bar: GNonEmpty[Any] = GNonEmpty(1,GNonEmpty(foo,GEmpty()))
class BadStack extends Stack[Double] {
override def push(e : Double) = { super.push(sqrt(e)) }
}
BadStack <: Stack[Double]Stack[Double] <: Stack[AnyRef]? It better not be:
Stack[AnyRef] bad = new BadStack();
bad.push("Yikes!"); // calls sqrt("Yikes!")
Ex. Can't have parameters of covariant T
class Stack[+T] {
def pop() : T = ... // OK
def push(newValue : T) { ... } // ERROR--T is parameter type
def isEmpty = ...
}
push variance problem by making push into a generic methodclass Stack[+T] {
def push[N >: T](newValue : N) : Stack[N] = new NonEmptyStack[N](newValue, this)
...
}
push (parameter is N) push in BadStackList<T>, Comparator<T>List<Person>, List<Student>public static void add(List<Person> people, List<? extends Person> morePeople) public static void sort(List<Person> people, Comparator<? super Person> comp)
public interface Function<T, R> {
default <V> Function<T,V> andThen(Function<? super R,? extends V> after)
...
}Function1[-T1, +R]
We'll start with these classes. Add them to a Scala file.
class Person(val name : String) {
override def toString = getClass.getName + "[name=" + name + "]"
}
class Student(name : String, val id : Int) extends Person(name) {
override def toString = super.toString + "[id=" + id + "]"
}
object Main extends App {
val harry = new Person("Harry Smith")
val sally = new Person("Sally Jones")
val diana = new Student("Diana Lee", 1729)
val frank = new Student("Frank Miller", 2525)
}
Student <: Person, that is, a Student object can be converted to the Person type.Array[Student] can not be converted to Array[Person].List instead of Array? Why?Person to a List[Student]? Does it work? If so, what is the type of the result?class MyPair[T](val first: T, val second: T)
Is MyPair(Student) a subtype of MyPair(Person)? How did you determine the answer? (Note: There is already a Pair[S, T] in Scala.)
MyPair class to fix the issue of the preceding question? (Hint: It's a very small change.)MyPair class:
def sum(f : Function1[T, Int]) = f(first) + f(second)
Make objects (with explicit types for extra clarity)
val f : Function1[Student, Int] = { x : Student => x.id }
val g : Function1[Person, Int] = { x : Person => x.name.length }
val p : MyPair[Student] = new MyPair(diana, frank)
Can you call p.sum(f)? p.sum(g)? If so, what are the results?
p.sum(f) works. p is a MyPair[Student] and f is a Function1[Student, Int]. But why does p.sum(g) work, even though the types don't match? MyPair class:
def max = if (first < second) second else first
Why won't the code compile?
MyPair class so that the max function compiles?new MyPair(17, 29).max. Did it compile? If not, what fix did you need to make?MyPair of two Person objects. What happens?MyPair[Student] and weep.