Introduction

At first glance, a Scala String appears to be just a Java String. For instance, when you work in the Scala Read-Evaluate-Print-Loop (REPL) environment (see Figure 1-1) and print the name of a String literal, the REPL feedback tells you the type is java.lang.String:

scala> "Hello, world".getClass.getName
res0: String = java.lang.String
The Scala REPL is an interactive environment where you can test Scala statements

Figure 1-1. The Scala REPL is an interactive environment where you can test Scala statements

Indeed, a Scala String is a Java String, so you can use all the normal Java string methods. You can create a string variable, albeit in the Scala way:

val s = "Hello, world"

You can get the length of a string:

s.length  // 12

You can concatenate strings:

val s = "Hello" + " world"

These are all familiar operations. But because Scala offers the magic of implicit conversions, String instances also have access to all the methods of the StringOps class, so you can do many other things with them, such as treating a String instance as a sequence of characters. As a result, you can iterate over every character in the string using the foreach method:

scala> "hello".foreach(println)
h
e
l
l
o

You can treat a String as a sequence of characters in a for loop:

scala> for (c <- "hello") println(c)
h
e
l
l
o

You can also treat it as a sequence of bytes:

scala> s.getBytes.foreach(println)
104
101
108
108
111

Because there are many methods available on sequential collections, you can also use other functional methods like filter:

scala> val result = "hello world".filter(_ != 'l')
result: String = heo word

It’s an oversimplification to say that this functionality comes from the StringOps class, but it’s a useful illusion. The reality is that some of this functionality comes from StringOps, some comes from StringLike, some from WrappedString, and so on. If you dig into the Scala source code, you’ll see that the rabbit hole goes deep, but it begins with the implicit conversion from String to StringOps in the Predef object.

Note

When first learning Scala, take a look at the source code for the Predef object. It provides nice examples of many Scala programming features.

Figure 1-2, taken from the StringOps class Scaladoc page, shows the supertypes and type hierarchy for the StringOps class.

Supertypes and type hierarchy information for the StringOps class

Figure 1-2. Supertypes and type hierarchy information for the StringOps class

Add Methods to Closed Classes

Even though the String class is declared as final in Java, you’ve seen that Scala somehow adds new functionality to it. This happens through the power of implicit conversions. Recipe 1.9, demonstrates how to add your own methods to the String class using this technique.

As one more example of how this pattern helps a Scala String have both string and collection features, the following code uses the drop and take methods that are available on Scala sequences, along with the capitalize method from the StringOps class:

scala> "scala".drop(2).take(2).capitalize
res0: String = Al

In this chapter you’ll see examples like this, and many more.

Get Scala Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.