A FEW MISCELLANEOUS ITEMS
https://docs.scala-lang.org/overviews/scala-book/misc.html
In this section we'll cover a few miscellaneous items about Scala:
- Tuples tuples
- Scala OOP example of pizza restaurant order entry system
TUPLES
https://docs.scala-lang.org/overviews/scala-book/tuples.html
Tuple is a concise class that provides you with a simple way to store heterogeneous (different) items in the same container. For example, suppose you have such a class:
class Person(var name: String)
You don't have to create a special class to store things, like this:
class SomeThings(i: Int, s: String, p: Person)
you can just create a tuple like this:
val t = (3, "Three", new Person("Al"))
As shown in the figure, just put some elements in parentheses and you have a tuple. Scala tuples can contain 2 to 22 items. They are very useful when you only need to put some things together and don't want to have to define the burden of a class, especially when the class feels a little "artificial" or fake.
Technically, Scala 2 X classes named Tuple2, Tuple3... Up to Tuple22. In fact, you rarely need to know this, but it's also good to know what's going on behind the scenes. (this architecture has been improved in Scala 3.)
A few more tuple details
This is a two element tuple:
scala> val d = ("Maggie", 30) d: (String, Int) = (Maggie,30)
Note that it contains two different types. This is a triple element:
scala> case class Person(name: String) defined class Person scala> val t = (3, "Three", new Person("David")) t: (Int, java.lang.String, Person) = (3,Three,Person(David))
There are several ways to access tuple elements. One way to access them is through the element number, where the number is preceded by an underscore:
scala> t._1 res1: Int = 3 scala> t._2 res2: java.lang.String = Three scala> t._3 res3: Person = Person(David)
Another cool way is to access them like this:
scala> val(x, y, z) = (3, "Three", new Person("David")) x: Int = 3 y: String = Three z: Person = Person(David)
Technically, this method involves a form of pattern matching, which is a good way to assign tuple elements to variables.
Returning a tuple from a method
This is a good place when you want to return multiple values from a method. For example, this is a method that returns tuples:
def getStockInfo = { // other code here ... ("NFLX", 100.00, 101.00) // this is a Tuple3 }
You can now call this method and assign the variable name to the return value:
val (symbol, currentPrice, bidPrice) = getStockInfo
The REPL demonstrates how this works:
scala> val (symbol, currentPrice, bidPrice) = getStockInfo symbol: String = NFLX currentPrice: Double = 100.0 bidPrice: Double = 101.0
Creating a class for the return type of a method like this feels a little overkill, and tuples are very convenient.
Tuples aren't collections
Technically, Scala 2 X tuples are not collection classes, they are just a convenient small container. Because they are not collections, they have no methods such as map, filter, etc.
AN OOP EXAMPLE
https://docs.scala-lang.org/overviews/scala-book/oop-pizza-example.html
This lesson shares a sample OOP application written in Scala. This example shows the code you might write for the order entry system for a pizza restaurant.
As shown earlier in this book, you can create enumerations in Scala like this:
sealed trait Topping case object Cheese extends Topping case object Pepperoni extends Topping case object Sausage extends Topping case object Mushrooms extends Topping case object Onions extends Topping sealed trait CrustSize case object SmallCrustSize extends CrustSize case object MediumCrustSize extends CrustSize case object LargeCrustSize extends CrustSize sealed trait CrustType case object RegularCrustType extends CrustType case object ThinCrustType extends CrustType case object ThickCrustType extends CrustType
One advantage of Scala is that even if we haven't discussed sealed trait or case objects, you can still figure out how this code works.
A few classes
Given these enumerations, you can now start creating some Pizza related classes for the order entry system. First, this is a Pizza class:
import scala.collection.mutable.ArrayBuffer class Pizza ( var crustSize: CrustSize, var crustType: CrustType, var toppings: ArrayBuffer[Topping] )
Next, here's an Order class, where an Order consists of a mutable list of pizzas and a Customer:
class Order ( var pizzas: ArrayBuffer[Pizza], var customer: Customer )
Here's a Customer class to work with that code:
class Customer ( var name: String, var phone: String, var address: Address )
Finally, here's an Address class:
class Address ( var street1: String, var street2: String, var city: String, var state: String, var zipCode: String )
So far, these classes look like data structures -- like structures in C -- so let's add some behavior.
Adding behavior to Pizza
In most cases, the OOP Pizza class requires some methods to add and remove toppings and adjust the size and type of the shell. This is a "Pizza" class that adds methods to handle these behaviors:
class Pizza ( var crustSize: CrustSize, var crustType: CrustType, val toppings: ArrayBuffer[Topping] ) { def addTopping(t: Topping): Unit = toppings += t def removeTopping(t: Topping): Unit = toppings -= t def removeAllToppings(): Unit = toppings.clear() }
You can also argue that pizza should be able to calculate its own price, so you can add another method to this class:
def getPrice( toppingsPrices: Map[Topping, Int], crustSizePrices: Map[CrustSize, Int], crustTypePrices: Map[CrustType, Int] ): Int = ???
Please note that this is a completely legal method??? Syntax is often used as a teaching tool, and sometimes you use it as a method sketch tool to say, "this is what my method signature looks like, but I don't want to write a method body." A good thing at that time was that the code could be compiled.
Having said that, don't call that method. If you do, you will get a not implemented error, which can describe this situation very well.
Adding behavior to Order
You should be able to perform some operations on the order, including:
- Add and remove pizza
- Update customer information
- Get order price
This is an Order class that allows you to do these things:
class Order ( val pizzas: ArrayBuffer[Pizza], var customer: Customer ) { def addPizza(p: Pizza): Unit = pizzas += p def removePizza(p: Pizza): Unit = pizzas -= p // need to implement these def getBasePrice(): Int = ??? def getTaxes(): Int = ??? def getTotalPrice(): Int = ??? }
Again, for this example, we don't care how to calculate the order price.
Testing those classes
You can test these classes with a small "driver" class. By adding a printOrder method in the Order class and a toString method in the Pizza class, you will find that the displayed code is as shown in the advertisement:
import scala.collection.mutable.ArrayBuffer object MainDriver extends App { val p1 = new Pizza ( MediumCrustSize, ThinCrustType, ArrayBuffer(Cheese) ) val p2 = new Pizza ( LargeCrustSize, ThinCrustType, ArrayBuffer(Cheese, Pepperoni, Sausage) ) val address = new Address ( "123 Main Street", "Apt. 1", "Talkeetna", "Alaska", "99676" ) val customer = new Customer ( "Alvin Alexander", "907-555-1212", address ) val o = new Order( ArrayBuffer(p1, p2), customer ) o.addPizza( new Pizza ( SmallCrustSize, ThinCrustType, ArrayBuffer(Cheese, Mushrooms) ) ) // print the order o.printOrder }
Experiment with the code yourself
To experiment with this yourself, see the pizza oopexample project in the GitHub repository of this book, which you can find at this URL:
To compile this project, it will help (a) use IntelliJ IDEA or Eclipse, or (b) know how to use it Scala Build Tool.