Channels ▼
RSS

JVM Languages

Scala for C# Developers: The Magic


In fact, Scala uses more implicit conversions than you might imagine in its base library. For example, the following code prints all the numbers in a range from 1 to 20:

(1 to 20).foreach(println _)

As you might guess, the previously shown code is equivalent to the following line because to is a method applied to 1, and 20 is the parameter for the method call. The to method creates a scala.collection.immutable.Range.Inclusive instance that starts with 1 and ends with 20 (an inclusive range).

(1.to(20)).foreach(println _)

1 and 20 are Int values. However, the to method is not defined in Int. It is included in the RichInt class. Scala implicitly converst Int to RichInt and calls the to method. Many other methods that you call with Int values are included in the RichInt class and perform implicit conversion, such as the toHexString method that returns the hexadecimal string for an integer, as in the following line:

10.toHexString

Mixin Class Composition

Scala makes it possible to reuse the delta between a class and its superclass. A simple example will demonstrate the power of this mixin class composition and show Scala's new way of thinking about inheritance.

The following lines define an abstract Neighbor class.

abstract class Neighbor {
	type T
	def hasLeftNeighbor: Boolean
	def hasRightNeighbor: Boolean
	def leftNeighbor: T
	def rightNeighbor: T
}

The following two mixin classes (GoodMoodNeighbor and BadMoodNeighbor) extend Neighbor. The first defines a greeting and the second a complaint. Because I want both classes to be used as mixins, I define them by using the trait keyword instead of class.

trait GoodMoodNeighbor extends Neighbor {
	def greeting: String = "Good morning!"
}

trait BadMoodNeighbor extends Neighbor {
	def complaint: String = "What a horrible morning!"
}

The following lines define a concrete NamedNeighbor class that extends the previously defined abstract Neighbor class; it also defines String as the type for Neighbor. Notice the usage of Option[String] to determine whether the neighbor has left or right neighbors.

class NamedNeighbor(val name: String, leftNeighborName: Option[String],
    rightNeighborName: Option[String]) extends Neighbor {
        type T = String
        def hasLeftNeighbor = leftNeighborName.isDefined
        def hasRightNeighbor = rightNeighborName.isDefined
        def leftNeighbor = leftNeighborName.getOrElse("There is no left neighbor")
        def rightNeighbor = rightNeighborName.getOrElse("There is no right neighbor")
}

Mixin class composition allows you to combine the functionality of the GoodMoodNeighbor trait and the NamedNeighbor concrete class. The following lines create an instance of NamedNeighbor with GoodMoodNeighbor. Notice that the with keyword after the constructor parameters for the NamedNeighbor class indicates Scala to combine the instance of NamedNeighbor with the GoodMoodNeighbor trait. Scala constructs the namedNeighborWithGoodMood instance from a mixin composition of NamedNeighbor and GoodMoodNeighbor.

val namedNeighborWithGoodMood = 
    new NamedNeighbor("Dr. Dobb's", 
        Some("Scala language"), Some("C# language")) with GoodMoodNeighbor

This way, you can access all the members defined in the NamedNeighbor concrete class and you can also call the greeting method defined in the GoodMoodNeighbor trait. As a result, the following lines will all provide the expected results:

namedNeighborWithGoodMood.name
namedNeighborWithGoodMood.greeting
namedNeighborWithGoodMood.hasLeftNeighbor
namedNeighborWithGoodMood.hasRightNeighbor
namedNeighborWithGoodMood.leftNeighbor
namedNeighborWithGoodMood.rightNeighbor

You can also define a new class that combines the NamedNeighbor class with the GoodMoodNeighbor trait. The following line shows an example of the syntax with the parameters for the NamedNeighbor class. In this case, NamedNeighbor is the superclass of NamedGoodMoodNeighbor, and the second parent (GoodMoodNeighbor) is a mixin.

class NamedGoodMoodNeighbor extends NamedNeighbor("Dr. Dobb's",
    Some("Scala language"), Some("C# language")) with GoodMoodNeighbor

Obviously, you can also combine the functionality of the BadMoodNeighbor trait and the NamedNeighbor concrete class. The following lines create an instance of NamedNeighbor with BadMoodNeighbor, so you can call the complaint method in the resulting instance.

val namedNeighborWithBadMood = new NamedNeighbor("Dr. Dobb's",
    Some("Scala language"), Some("C# language")) with BadMoodNeighbor

It is also possible to include more mixins. For example, you can combine the functionality of the BadMoodNeighbor trait, the GoodMoodNeighbor trait and the NamedNeighbor concrete class. The following lines create an instance of NamedNeighbor with GoodMoodNeighbor with BadMoodNeighbor; therefore, you can call both the greeting and complaint methods in the resulting instance.

val namedNeighborWithBothMoods = new NamedNeighbor("Dr. Dobb's", 
    Some("Scala language"), Some("C# language")) 
    with GoodMoodNeighbor with BadMoodNeighbor

Mixin class composition is extremely powerful and allows you to stop thinking about thin interfaces and take advantage of this different kind of inheritance.

Conclusion

As you've seen in this article, there are many really useful features in Scala, which are easy to learn — especially if you're familiar with C#. I hope this three-part series has whet your appetite about what's possible in Scala. As I mentioned in the first article, the principal Scala site is the mother ship, which you should consult for more documentation and tutorials.


Gaston Hillar is a frequent contributor to Dr. Dobb's.

Earlier Installments in this series:

Scala For C# Developers: Part 1 — Getting Started

Scala for C# Developers: Part 2 — Useful Features


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video