【正文】
1 來自: think in java ( 3) 外文原文 The busy Java developer39。s guide to Scala: Class action It makes sense for Java? developers to use objects as a first point of reference for understanding Scala. In this second installment of The busy Java developer39。s guide to Scala series, Ted Neward follows a basic premise of language measurement: that the power of a language can be measured in direct relation to its ability to integrate new facilities in this case, support for plex numbers. Along the way you39。ll see some interesting tidbits related to class definitions and usage in Scala. In last month39。s article , you saw just a touch of Scala39。s syntax, the bare minimum necessary to run a Scala program and observe some of its simpler features. The Hello World and Timer examples from that article let you see Scala39。s Application class, its syntax for method definitions and anonymous functions, just a glimpse of an Array[], and a bit on typeinferencing. Scala has a great deal more to offer, so this article investigates the intricacies of Scala coding. Scala39。s functional programming features are pelling, but they39。re not the only reason Java developers should be interested in the language. In fact, Scala blends functional concepts and object orientation. In order to let the JavacumScala programmer feel more at home, it makes sense to look at Scala39。s object features and see how they map over to Java linguistically. Bear in mind that there isn39。t a direct mapping for some of these features, or in some cases, the mapping is more of an analog than a direct parallel. But where the distinction is important, I39。ll point it out. Scala has class(es), too Rather than embark on a lengthy and abstract discussion of the class features that Scala supports, let39。s look at a definition for a class that might be used to bring rational number support to the Scala platform (largely swiped from Scala By Example see Resources): Listing 1. class Rational(n:Int, d:Int) { private def gcd(x:Int, y:Int): Int = { if (x==0) y else if (x0) gcd(x, y) else if (y0) gcd(x, y) 2 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* + *denom, denom * ) def (that:Rational) = new Rational(numer * * denom, denom * ) def *(that:Rational) = new Rational(numer * , denom * ) def /(that:Rational) = new Rational(numer * , denom * ) override def toString() = Rational: [ + numer + / + denom + ] } While the overall structure of Listing 1 is lexically similar to what you39。ve seen in Java code over the last decade, some new elements clearly are at work here. Before picking this definition apart, take a look at the code to exercise the 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 (r1 = + r1) (r2 = + r2) (r3 = r1 r2 = + r3) 3 (r4 = r1 + r2 = + r4) } What you see in Listing 2 isn39。t terribly exciting: I create a couple of rational numbers, create two more Rationals as the addition and subtraction of the first two, and echo everything to the console. (Note that () es from the Scala core library, living in scala.*, and is implicitly imported into every Scala program, just as is in Java programming.) How many ways shall I construct thee? Now look again at the first line in the Rational class definition: Listing 3. Scala39。s default constructor class Rational(n:Int, d:Int) { // ... Although you might think you39。re looking at some kind of genericslike syntax in Listing 3, it39。s actually the default and preferred constructor for the Rational class: n and d are simply the parameters to that constructor. Scala39。s preference for a single constructor makes a certain kind of sense most classes end up having a single constructor or a collection of constructors that all chain through a single constructor as a convenience. If you wanted to, you could define more constructors on a Rational like so: Listing 4. A chain of constructors class Rational(n:Int, d:Int) { def this(d:Int) = { this(0, d) } Note that Scala39。s constructor chain does the usual Javaconstructorchaining thing by calling into the preferred constructor (the Int,Int version). Details, (implementation) details... When working with rational numbers, it helps to perform a bit of numerical legerdemain: namely that of finding a mon denominator to make certain operations easier. If you want to add 1over2 (also known as onehalf) to 2over4 (also known as twofourths), the Rational class should be smart enough to realize that 2over4 is the same as 1over2, and convert it accordingly before adding the two together. 4 This is the purpose of the nested private gcd() function and g value inside of the Rational class. When the constructor is invoked in Scala, the entire body of the class is evaluated, which means g will be initialized with the greatest mon denominator of n and d, and then used in turn to set n and d appropriately. Looking back at Listing 1, it39。s also fairly easy to see that I created an overridden toString method to return the values of Rational, which will be very useful when I start exercising it from the RunRational driver code. Notice the syntax around toString, however: the override keyword in the front of the definition is required so that Scala can check to make sure that a corresponding definition exists in the base class. This can help prevent subtle bugs created by accidental keyboard slips. (It was this same motivation that led to