Java™ developers can use objects as a starting point for understanding Scala. This is the second phase of the Scala Guide series for Java developers, and the author Ted Neward follows the basic premise of evaluating a language: the power of a language can be measured directly by its ability to integrate new functionality, which in this article refers to support for complex numbers. Following this article, you will learn some interesting features related to the definition and use of classes in Scala.
In the previous installment, you only had a little knowledge of Scala syntax, which is the most basic requirement for running Scala programs and understanding their simple features. With the Hello World and Timer sample program in the previous article, you learned about Scala's application classes, method definitions, and anonymous function syntax, and a little bit about array[] and some types of inference. Scala also offers a number of other features, and this article will look at some of the more complex aspects of Scala programming.
Scala's functional programming features are compelling, but that's not the only reason Java developers should be interested in the language. In fact, Scala blends functional concepts with object-oriented concepts. To make Java and Scala programmers feel comfortable, take a look at Scala's object features and see how they correspond to Java in terms of language. Remember, some of these features do not correspond directly, or, in some cases, "correspondence" is more like an analogy than a direct counterpart. However, when there are important differences, I will point them out.
Use classes like Scala and Java
Instead of a lengthy and abstract discussion of the class features that Scala supports, we look at the definition of a class that can be used to introduce support for the Scala platform for rational numbers (mainly from "Scala by Example", see Resources):
Listing 1. Rational.scala
class Rational(n:Int, d:Int)
{
private def gcd(x:Int, y:Int): Int =
{
if (x==0) y
else if (x<0) gcd(-x, y)
else if (y<0) -gcd(x, -y)
else gcd(y%x, x)
}
private val g = gcd(n,d)
val numer:Int = n/g
val denom:Int = d/g
def +(that:Rational) =
new Rational(numer*that.denom + that.numer*denom, denom * that.denom)
def -(that:Rational) =
new Rational(numer * that.denom - that.numer * denom, denom * that.denom)
def *(that:Rational) =
new Rational(numer * that.numer, denom * that.denom)
def /(that:Rational) =
new Rational(numer * that.denom, denom * that.numer)
override def toString() =
"Rational: [" + numer + " / " + denom + "]"
}
The overall structure of listing 1 is similar to Java code in terms of vocabulary, but there are obviously some new elements here. Before we discuss this definition in detail, let's look at a piece of code that uses this new Rational class:
Listing 2. Runrational
class Rational(n:Int, d:Int)
{
// ... as before
}
object RunRational extends Application
{
val r1 = new Rational(1, 3)
val r2 = new Rational(2, 5)
val r3 = r1 - r2
val r4 = r1 + r2
Console.println("r1 = " + r1)
Console.println("r2 = " + r2)
Console.println("r3 = r1 - r2 = " + r3)
Console.println("r4 = r1 + r2 = " + r4)
}