Scala学习之Tuples和OOP 示例

Posted 顧棟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala学习之Tuples和OOP 示例相关的知识,希望对你有一定的参考价值。

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 元组
  • 比萨餐厅订单输入系统的 Scala OOP 示例

TUPLES

https://docs.scala-lang.org/overviews/scala-book/tuples.html

元组是一个简洁的类,它为您提供了一种在同一个容器中存储异构(不同)项目的简单方法。 例如,假设你有一个这样的类:

class Person(var name: String)

不必创建一个专门的类来存储东西,就像这样:

class SomeThings(i: Int, s: String, p: Person)

you can just create a tuple like this:

val t = (3, "Three", new Person("Al"))

如图所示,只需将一些元素放在括号内,您就有了一个元组。 Scala 元组可以包含 2 到 22 个项目,当您只需要将一些东西组合在一起并且不希望必须定义一个类的包袱时,它们非常有用,尤其是当该类感觉有点时 “人造的”或假的。

从技术上讲,Scala 2.x 有名为 Tuple2、Tuple3 ……直到 Tuple22 的类。 实际上,您很少需要知道这一点,但了解幕后发生的事情也很好。 (这个架构在 Scala 3 中得到了改进。)

A few more tuple details

这是一个二个元素元组:

scala> val d = ("Maggie", 30)
d: (String, Int) = (Maggie,30)

请注意,它包含两种不同的类型。 这是一个三元素元组:

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))

有几种方法可以访问元组元素。 一种方法是通过元素编号访问它们,其中数字前面有一个下划线:

scala> t._1
res1: Int = 3

scala> t._2
res2: java.lang.String = Three

scala> t._3
res3: Person = Person(David)

另一种很酷的方法是像这样访问它们:

scala> val(x, y, z) = (3, "Three", new Person("David"))
x: Int = 3
y: String = Three
z: Person = Person(David)

从技术上讲,这种方法涉及一种模式匹配形式,它是将元组元素分配给变量的好方法。

Returning a tuple from a method

当你想从一个方法返回多个值时,这是一个很好的地方。 例如,这是一个返回元组的方法:

def getStockInfo = {
    // other code here ...
    ("NFLX", 100.00, 101.00)  // this is a Tuple3
}

现在您可以调用该方法并将变量名称分配给返回值:

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

对于像这种为方法的返回类型创建一个类感觉有点矫枉过正的情况,元组非常方便。

Tuples aren’t collections

从技术上讲,Scala 2.x 元组不是集合类,它们只是一个方便的小容器。 因为它们不是集合,所以它们没有 map、filter 等方法。

AN OOP EXAMPLE

https://docs.scala-lang.org/overviews/scala-book/oop-pizza-example.html

本课分享一个使用 Scala 编写的 OOP 应用程序示例。 该示例显示了您可能为比萨店的订单输入系统编写的代码。

如本书前面所示,您可以像这样在 Scala 中创建枚举:

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

Scala 的一个好处是,即使我们还没有讨论过密封的 trait 或 case 对象,你仍然可以弄清楚这段代码是如何工作的。

A few classes

鉴于这些枚举,您现在可以开始为订单输入系统创建一些与比萨饼相关的类。 首先,这是一个 Pizza 类:

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
)

到目前为止,这些类看起来像数据结构——就像 C 中的结构——所以让我们添加一些行为。

Adding behavior to Pizza

大多数情况下,OOP Pizza 类需要一些方法来添加和删除浇头,并调整外壳的大小和类型。 这是一个“Pizza”类,其中添加了一些方法来处理这些行为:

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()

}

您还可以争辩说,披萨应该能够计算自己的价格,因此您可以向该类添加另一种方法:

def getPrice(
    toppingsPrices: Map[Topping, Int],
    crustSizePrices: Map[CrustSize, Int],
    crustTypePrices: Map[CrustType, Int]
): Int = ???

请注意,这是一种完全合法的方法。 ??? 语法通常用作教学工具,有时您将其用作方法草图工具来说:“这就是我的方法签名的样子,但我不想写方法体 然而。” 那个时候的一件好事是这段代码可以编译。

话虽如此,不要调用那个方法。 如果你这样做了,你会得到一个NotImplementedError,它非常能描述这种情况。

Adding behavior to Order

您应该能够对订单执行一些操作,包括:

  • 添加和删除比萨饼
  • 更新客户信息
  • 获取订单价格

这是一个 Order 类,可以让你做这些事情:

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 = ???

}

再一次,就本示例而言,我们不关心如何计算订单价格。

Testing those classes

您可以使用一个小的“驱动程序”类来测试这些类。 通过在 Order 类中添加一个 printOrder 方法并在 Pizza 类中添加一个 toString 方法,你会发现显示的代码如广告所示:

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

要自己对此进行试验,请参阅本书 GitHub 存储库中的 PizzaOopExample项目,您可以在此 URL 中找到该项目:

要编译这个项目,这将有助于 (a) 使用 IntelliJ IDEA 或 Eclipse,或 (b) 知道如何使用 Scala Build Tool

以上是关于Scala学习之Tuples和OOP 示例的主要内容,如果未能解决你的问题,请参考以下文章

Scala深入学习之函数学习

Scala基础学习之for循环和while循环

大数据学习之Scala语言基本语法学习36

Scala学习之爬豆瓣电影

Scala入门学习之包类与对象

Scala 学习之「类——基本概念3」