I> Return Type/Type Inference : Mechanism where return Type is automatically inferred.
II> Parameters : Scope and mechanisms for passing variables
III> Generics : Generic way of passing and returning parameters.
IV> Polymorphism : Overriding of methods and mechanism to do the same.
V> Passing Parameters i.e either by call by name or call by reference.
Call by name is a new feature provided as part of scala.
Below are some examples which details on the method declarations
Type Inference Example
object TypeInference {
def main(args: Array[String]) {
println(methodReturnNotImplicit);
println(methodReturnImplicit);
}
def methodReturnNotImplicit() = {
"Hello From methodReturnNotImplicit"
}
def methodReturnImplicit():String = {
"Hello From methodReturnImplicit"
}
}
Generics
object ScalaGenerics {
def main(args: Array[String]) {
printGenerics(List(1,2,4,8))
printGenerics(List("David","John","Steve"))
printSize(List(1,2,4,8))
}
def printGenerics[T](p:List[T]) = {
for{i <- 0 to p.size-1}
println(p(i))
}
def printSize[T](p:List[T]) = {
println("size from length " +p.length)
println("size from size " +p.size)
}
}
Observations
1. One Single method is being used for printing both Integers and Strings.
2. Elements in Scala List begin from size 0 instead of 1 unlike in java.
3. Scala has both length and size method for List.. Surprising.. Oh yes.. I was surprised too :-)
Variable Length Parameters
object VariableLengthParameter {
def main(args: Array[String]) {
println(printSum(1,2,4,8))
println(printLength(1,2,4,8))
println(printLength("David","John"))
}
def printSum(p:Int*) = {
p.reduceLeft((a,b)=> a+b)
}
def printLength[T](p:T*) = {
p.length
}
}
Observations
1. Ensure to use only those operations which are available on generic T object.
For Example if we had used
def printSum(p:T*) = {
p.reduceLeft((a,b)=> a+b)
}
Then the compiler would complain that the operation + is not allowed on generics.
Nested Methods
object NestedMethods {
def main(args: Array[String]) {
println(parentMethod)
}
def parentMethod() = {
var count=0
def nestedMethod() = {
count = count +1
println("count inside nestedMethod " +count)
}
for{i <- 0 to 4 }
nestedMethod()
println(count)
}
}
Observations
1. One can Nest Methods in scala except at the top level where classes,traits are declared.
2. Methods can access variables declared in the parent methods but parent methods cannot access variables declared in the child methods.
Polymorphism
object OverridingMethods {
def main(args: Array[String]) {
var b = new BaseImpl
var b2 = new BaseImpl2
var b3 = new BaseImpl3
println(b.support)
println(b2.support)
println(b3.support)
}
}
abstract class Base {
def support:String
}
class BaseImpl extends Base {
def support:String=" Hello"
}
class BaseImpl2 extends BaseImpl {
override def support:String=" Hello From BaseImpl2"
}
class BaseImpl3 extends BaseImpl2 {
override val support = "Hello From BaseImpl3"
}
Observations
1. One of the observations has been cant use Base b = new BaseImpl.. Scala doesnt support this notation.
2. Override declarator not required since we are extending abstract class. It is optional
3. Override declarator is required if extending a base class.
4. A variable can be used for overriding a method in a base class.
Call by Name Vs Call by Reference
object CallByNameMain {
def main(args: Array[String]) {
passTime(getTime())
}
def getTime() = {
println("Getting time from getTime");
System.nanoTime
}
def passTime(t: => Long) {
println("Inside PassTime");
println(t);
}
}
object CallByReferenceMain {
def main(args: Array[String]) {
passTime(getTime())
}
def getTime() = {
println("Getting time from getTime");
System.nanoTime
}
def passTime(t:Long) {
println("Inside PassTime");
println(t);
}
}
Observations
1. Also known as delayed or lazy execution, call by name mechanism allows one to pass a block of code which is executed only when the block of code is accessed with in the referenced code.
2. Call by Name is denoted as :=> and Call by Reference is denoted as :

No comments:
Post a Comment