Scala 3 โ€” Book

ๅ‘ Java ๅผ€ๅ‘่€…ไป‹็ปScala

Language

ๆญค้กต้ข้€š่ฟ‡ๅ…ฑไบซๆฏ็ง่ฏญ่จ€็š„ๅนถๆŽ’็คบไพ‹๏ผŒๅฏน Java ๅ’Œ Scala ็ผ–็จ‹่ฏญ่จ€่ฟ›่กŒไบ†ๆฏ”่พƒใ€‚ ๅฎƒ้€‚็”จไบŽไบ†่งฃ Java ๅนถๅธŒๆœ›ไบ†่งฃ Scala ็š„็จ‹ๅบๅ‘˜๏ผŒ็‰นๅˆซๆ˜ฏ้€š่ฟ‡ Scala ็‰นๆ€งไธŽ Java ็‰นๆ€ง็š„ๅฏนๆฏ”ๆฅไบ†่งฃใ€‚

ๆฆ‚่ฟฐ

ๅœจ่ฟ›ๅ…ฅ็คบไพ‹ไน‹ๅ‰๏ผŒ็ฌฌไธ€้ƒจๅˆ†ๆไพ›ไบ†ไปฅไธ‹้ƒจๅˆ†็š„็›ธๅฏน็ฎ€็Ÿญ็š„ไป‹็ปๅ’Œๆ€ป็ป“ใ€‚ ๅฎƒไปŽ้ซ˜ๅฑ‚ๆฌกไธŠไป‹็ปไบ† Java ๅ’Œ Scala ไน‹้—ด็š„ๅผ‚ๅŒ๏ผŒ็„ถๅŽไป‹็ปไบ†ๆ‚จๅœจๆฏๅคฉ็ผ–ๅ†™ไปฃ็ ๆ—ถไผš้‡ๅˆฐ็š„ๅทฎๅผ‚ใ€‚

้ซ˜ๅฑ‚ๆฌก็š„็›ธไผผๆ€ง

ๅœจ้ซ˜ๅฑ‚ๆฌกไธŠ๏ผŒScala ไธŽ Java ๆœ‰ไปฅไธ‹็›ธไผผไน‹ๅค„๏ผš

  • Scalaไปฃ็ ็ผ–่ฏ‘ๆˆ_.class_ๆ–‡ไปถ๏ผŒๆ‰“ๅŒ…ๆˆJARๆ–‡ไปถ๏ผŒ่ฟ่กŒๅœจJVMไธŠ
  • ่ฟ™ๆ˜ฏไธ€็ง้ขๅ‘ๅฏน่ฑก็ผ–็จ‹ (OOP) ่ฏญ่จ€
  • ๅฎƒๆ˜ฏ้™ๆ€็ฑปๅž‹็š„
  • ไธค็ง่ฏญ่จ€้ƒฝๆ”ฏๆŒ lambdas ๅ’Œ ้ซ˜้˜ถๅ‡ฝๆ•ฐ
  • ๅฎƒไปฌ้ƒฝๅฏไปฅไธŽ IntelliJ IDEA ๅ’Œ Microsoft VS Code ็ญ‰ IDE ไธ€่ตทไฝฟ็”จ
  • ๅฏไปฅไฝฟ็”จ Gradleใ€Ant ๅ’Œ Maven ็ญ‰ๆž„ๅปบๅทฅๅ…ทๆž„ๅปบ้กน็›ฎ
  • ๅฎƒๅ…ทๆœ‰็”จไบŽๆž„ๅปบๆœๅŠกๅ™จ็ซฏใ€็ฝ‘็ปœๅฏ†้›†ๅž‹ๅบ”็”จ็จ‹ๅบ็š„ๅ‡บ่‰ฒๅบ“ๅ’Œๆก†ๆžถ๏ผŒๅŒ…ๆ‹ฌ Web ๆœๅŠกๅ™จๅบ”็”จ็จ‹ๅบใ€ๅพฎๆœๅŠกใ€ๆœบๅ™จๅญฆไน ็ญ‰๏ผˆๅ‚่ง โ€œAwesome Scalaโ€ ๅˆ—่กจ๏ผ‰
  • Java ๅ’Œ Scala ้ƒฝๅฏไปฅไฝฟ็”จ Scala ๅบ“๏ผš
    • ไป–ไปฌๅฏไปฅไฝฟ็”จ Akka actor ๅบ“ ๆฅๆž„ๅปบๅŸบไบŽ actor ็š„ๅนถๅ‘็ณป็ปŸ๏ผŒๅนถไฝฟ็”จ Apache Spark ๆฅๆž„ๅปบๆ•ฐๆฎๅฏ†้›†ๅž‹ๅบ”็”จ็จ‹ๅบ
    • ไป–ไปฌๅฏไปฅไฝฟ็”จ Play Framework ๅผ€ๅ‘ๆœๅŠกๅ™จ็ซฏๅบ”็”จ็จ‹ๅบ
  • ๆ‚จๅฏไปฅไฝฟ็”จ GraalVM ๅฐ†ๆ‚จ็š„้กน็›ฎ็ผ–่ฏ‘ไธบๆœฌๆœบๅฏๆ‰ง่กŒๆ–‡ไปถ
  • Scala ๅฏไปฅๆ— ็ผไฝฟ็”จไธบ Java ๅผ€ๅ‘็š„ๅคง้‡ๅบ“

้ซ˜ๅฑ‚ๆฌก็š„ๅทฎๅผ‚

ๅŒๆ ทๅœจ้ซ˜ๅฑ‚ๆฌกไธŠ๏ผŒJava ๅ’Œ Scala ไน‹้—ด็š„ๅŒบๅˆซๆ˜ฏ๏ผš

  • Scala ่ฏญๆณ•็ฎ€ๆดๆ˜“่ฏป๏ผ›ๆˆ‘ไปฌ็งฐไน‹ไธบ_่กจ็ŽฐๅŠ›_
  • ่™ฝ็„ถๅฎƒๆ˜ฏ้™ๆ€็ฑปๅž‹็š„๏ผŒไฝ† Scala ็ปๅธธๆ„Ÿ่ง‰ๅƒๆ˜ฏไธ€้—จๅŠจๆ€่ฏญ่จ€
  • Scala ๆ˜ฏไธ€็ง็บฏ OOP ่ฏญ่จ€๏ผŒๅ› ๆญคๆฏไธชๅฏน่ฑก้ƒฝๆ˜ฏ็ฑป็š„ไธ€ไธชๅฎžไพ‹๏ผŒ่€Œๅƒ่ฟ็ฎ—็ฌฆไธ€ๆ ท็š„็ฌฆๅท + ๅ’Œ += ๆ˜ฏ็œŸๆญฃ็š„ๆ–นๆณ•๏ผ›่ฟ™ๆ„ๅ‘ณ็€ๆ‚จๅฏไปฅๅˆ›ๅปบ่‡ชๅทฑ็š„่ฟ็ฎ—็ฌฆ
  • ้™คไบ†ๆ˜ฏ็บฏOOP่ฏญ่จ€๏ผŒScala่ฟ˜ๆ˜ฏ็บฏFP่ฏญ่จ€๏ผ›ๅฎž้™…ไธŠ๏ผŒๅฎƒ้ผ“ๅŠฑ OOP ๅ’Œ FP ็š„่žๅˆ๏ผŒๅ…ทๆœ‰็”จไบŽ้€ป่พ‘็š„ๅ‡ฝๆ•ฐๅ’Œ็”จไบŽๆจกๅ—ๅŒ–็š„ๅฏน่ฑก
  • Scala ๆ‹ฅๆœ‰ไธ€ๆ•ดๅฅ—ไธๅฏๅ˜้›†ๅˆ๏ผŒๅŒ…ๆ‹ฌ Listใ€Vector ๅ’Œไธๅฏๅ˜็š„ Map ๅ’Œ Set ๅฎž็Žฐ
  • Scala ไธญ็š„ไธ€ๅˆ‡้ƒฝๆ˜ฏไธ€ไธช_่กจ่พพๅผ_๏ผšๅƒ if ่ฏญๅฅใ€for ๅพช็Žฏใ€match ่กจ่พพๅผ๏ผŒ็”š่‡ณ try/catch ่กจ่พพๅผ้ƒฝๆœ‰่ฟ”ๅ›žๅ€ผ
  • Scala ไน ๆƒฏไธŠๅ€พๅ‘็ผบ็œไฝฟ็”จไธๅฏๅ˜ๆ€ง๏ผš้ผ“ๅŠฑๆ‚จไฝฟ็”จไธๅฏๅ˜๏ผˆfinal๏ผ‰ๅ˜้‡ๅ’Œไธๅฏๅ˜้›†ๅˆ
  • ๆƒฏ็”จ็š„ Scala ไปฃ็ ไธไฝฟ็”จ null๏ผŒๅ› ๆญคไธไผš้ญๅ— NullPointerException
  • Scala ็”Ÿๆ€็ณป็ปŸๅœจ sbtใ€Mill ็ญ‰ไธญ่ฟ˜ๆœ‰ๅ…ถไป– ๆž„ๅปบๅทฅๅ…ท
  • ้™คไบ†ๅœจ JVM ไธŠ่ฟ่กŒไน‹ๅค–๏ผŒScala.js ้กน็›ฎๅ…่ฎธๆ‚จไฝฟ็”จ Scala ไฝœไธบ JavaScript ๆ›ฟไปฃๅ“
  • Scala Native ้กน็›ฎๆทปๅŠ ไบ†ไฝŽ็บง็ป“ๆž„๏ผŒ่ฎฉๆ‚จๅฏไปฅ็ผ–ๅ†™โ€œ็ณป็ปŸโ€็บงไปฃ็ ๏ผŒไนŸๅฏไปฅ็ผ–่ฏ‘ไธบๆœฌๆœบๅฏๆ‰ง่กŒๆ–‡ไปถ

็ผ–็จ‹ๅฑ‚ๆฌกๅทฎๅผ‚

ๆœ€ๅŽ๏ผŒ่ฟ™ไบ›ๆ˜ฏๆ‚จๅœจ็ผ–ๅ†™ไปฃ็ ๆ—ถๆฏๅคฉ้ƒฝไผš็œ‹ๅˆฐ็š„ไธ€ไบ›ๅทฎๅผ‚๏ผš

  • Scala ็š„่ฏญๆณ•ๆžๅ…ถไธ€่‡ด
  • ๅ˜้‡ๅ’Œๅ‚ๆ•ฐ่ขซๅฎšไน‰ไธบval๏ผˆไธๅฏๅ˜๏ผŒๅฆ‚Javaไธญ็š„final๏ผ‰ๆˆ–var๏ผˆๅฏๅ˜๏ผ‰
  • ็ฑปๅž‹ๆŽจๅฏผ ่ฎฉๆ‚จ็š„ไปฃ็ ๆ„Ÿ่ง‰ๆ˜ฏๅŠจๆ€็ฑปๅž‹็š„๏ผŒๅนถๆœ‰ๅŠฉไบŽไฟๆŒๆ‚จ็š„ไปฃ็ ็ฎ€ๆด
  • ้™คไบ†็ฎ€ๅ•็š„ for ๅพช็Žฏไน‹ๅค–๏ผŒScala ่ฟ˜ๅ…ทๆœ‰ๅผบๅคง็š„ for comprehensions๏ผŒๅฏไปฅๆ นๆฎๆ‚จ็š„็ฎ—ๆณ•ไบง็”Ÿ็ป“ๆžœ
  • ๆจกๅผๅŒน้…ๅ’Œ match ่กจ่พพๅผๅฐ†ๆ”นๅ˜ไฝ ็ผ–ๅ†™ไปฃ็ ็š„ๆ–นๅผ
  • ้ป˜่ฎคๆƒ…ๅ†ตไธ‹็ผ–ๅ†™ไธๅฏๅ˜ไปฃ็ ไผšๅฏผ่‡ด็ผ–ๅ†™_่กจ่พพๅผ_่€Œไธๆ˜ฏ_่ฏญๅฅ_๏ผ›้š็€ๆ—ถ้—ด็š„ๆŽจ็งป๏ผŒๆ‚จไผšๅ‘โ€‹โ€‹็Žฐ็ผ–ๅ†™่กจ่พพๅผๅฏไปฅ็ฎ€ๅŒ–ๆ‚จ็š„ไปฃ็ ๏ผˆๅ’Œๆ‚จ็š„ๆต‹่ฏ•๏ผ‰
  • ้กถๅฑ‚ๅฎšไน‰ ่ฎฉๆ‚จๅฏไปฅๅฐ†ๆ–นๆณ•ใ€ๅญ—ๆฎตๅ’Œๅ…ถไป–ๅฎšไน‰ๆ”พๅœจไปปไฝ•ๅœฐๆ–น๏ผŒๅŒๆ—ถไนŸๅธฆๆฅ็ฎ€ๆดใ€ๅฏŒๆœ‰่กจ็ŽฐๅŠ›็š„ไปฃ็ 
  • ๆ‚จๅฏไปฅ้€š่ฟ‡ๅฐ†ๅคšไธช traits โ€œๆททๅˆโ€ๅˆฐ็ฑปๅ’Œๅฏน่ฑกไธญๆฅๅˆ›ๅปบ_ๆททๆญ_๏ผˆ็‰นๅพ็ฑปไผผไบŽ Java 8 ๅ’Œๆ›ดๆ–ฐ็‰ˆๆœฌไธญ็š„ๆŽฅๅฃ๏ผ‰
  • ้ป˜่ฎคๆƒ…ๅ†ตไธ‹็ฑปๆ˜ฏๅฐ้—ญ็š„๏ผŒๆ”ฏๆŒ Joshua Bloch ๅœจ Effective Java ็š„ไน ๆƒฏ็”จๆณ•๏ผŒโ€œDesign and document for inheritance or else forbid itโ€
  • Scala ็š„ ไธŠไธ‹ๆ–‡ๆŠฝ่ฑก ๅ’Œ ๆœฏ่ฏญๆŽจๅฏผ ๆไพ›ไบ†ไธ€็ณปๅˆ—็‰นๆ€ง๏ผš
    • ๆ‰ฉๅฑ•ๆ–นๆณ• ่ฎฉๆ‚จๅ‘ๅฐ้—ญ็ฑปๆทปๅŠ ๆ–ฐๅŠŸ่ƒฝ
    • [็ป™_ๅฎžไพ‹]givens ่ฎฉๆ‚จๅฎšไน‰็ผ–่ฏ‘ๅ™จๅฏไปฅๅœจ _using ็‚นๅˆๆˆ็š„ๆœฏ่ฏญ๏ผŒไปŽ่€Œไฝฟๆ‚จ็š„ไปฃ็ ไธ้‚ฃไนˆๅ†—้•ฟ๏ผŒๅฎž่ดจไธŠ่ฎฉ็ผ–่ฏ‘ๅ™จไธบๆ‚จ็ผ–ๅ†™ไปฃ็ 
    • ๅคšๅ…ƒ็ญ‰ๅผ ๅ…่ฎธๆ‚จๅœจ็ผ–่ฏ‘ๆ—ถๅฐ†็›ธ็ญ‰ๆฏ”่พƒ้™ๅˆถไธบไป…้‚ฃไบ›ๆœ‰ๆ„ไน‰็š„ๆฏ”่พƒ
  • Scala ๆ‹ฅๆœ‰ๆœ€ๅ…ˆ่ฟ›็š„็ฌฌไธ‰ๆ–นๅผ€ๆบๅ‡ฝๆ•ฐๅผ็ผ–็จ‹ๅบ“
  • Scala ๆ ทไพ‹็ฑปๅฐฑๅƒ Java 14 ไธญ็š„่ฎฐๅฝ•๏ผ›ๅฎƒไปฌๅฏไปฅๅธฎๅŠฉๆ‚จๅœจ็ผ–ๅ†™ FP ไปฃ็ ๆ—ถๅฏนๆ•ฐๆฎ่ฟ›่กŒๅปบๆจก๏ผŒๅนถๅ†…็ฝฎๅฏนๆจกๅผๅŒน้…ๅ’Œๅ…‹้š†็ญ‰ๆฆ‚ๅฟต็š„ๆ”ฏๆŒ
  • ็”ฑไบŽๅ็งฐๅ‚ๆ•ฐใ€ไธญ็ผ€็ฌฆๅทใ€ๅฏ้€‰ๆ‹ฌๅทใ€ๆ‰ฉๅฑ•ๆ–นๆณ•ๅ’Œ ้ซ˜้˜ถๅ‡ฝๆ•ฐ ็ญ‰ๅŠŸ่ƒฝ๏ผŒๆ‚จๅฏไปฅๅˆ›ๅปบ่‡ชๅทฑ็š„โ€œๆŽงๅˆถ็ป“ๆž„โ€ๅ’Œ DSL
  • Scala ๆ–‡ไปถไธๅฟ…ๆ นๆฎๅฎƒไปฌๅŒ…ๅซ็š„็ฑปๆˆ– trait ๆฅๅ‘ฝๅ
  • ่ฎธๅคšๅ…ถไป–ๅฅฝไธœ่ฅฟ๏ผšไผด็”Ÿ็ฑปๅ’Œๅฏน่ฑกใ€ๅฎใ€่”ๅˆ ๅ’Œ ไบค้›†ใ€ๆ•ฐๅญ—ๅญ—้ข้‡ใ€ๅคšๅ‚ๆ•ฐๅˆ—่กจใ€ๅ‚ๆ•ฐ็š„้ป˜่ฎคๅ€ผใ€ๅ‘ฝๅๅ‚ๆ•ฐ็ญ‰

็”จไพ‹ๅญๆฅ่ฟ›่กŒ็‰นๆ€งๅฏนๆฏ”

้‰ดไบŽ่ฏฅไป‹็ป๏ผŒไปฅไธ‹้ƒจๅˆ†ๆไพ›ไบ† Java ๅ’Œ Scala ็ผ–็จ‹่ฏญ่จ€ๅŠŸ่ƒฝ็š„ๅนถๆŽ’ๆฏ”่พƒใ€‚

OOP ้ฃŽๆ ผ็š„็ฑปๅ’Œๆ–นๆณ•

ๆœฌ่Š‚ๆไพ›ไบ†ไธŽ OOP ้ฃŽๆ ผ็š„็ฑปๅ’Œๆ–นๆณ•็›ธๅ…ณ็š„็‰นๆ€ง็š„ๆฏ”่พƒใ€‚

ๆณจ้‡Š๏ผš

//
/* ... */
/** ... */
//
/* ... */
/** ... */

OOP ้ฃŽๆ ผ็ฑป๏ผŒไธปๆž„้€ ๅ‡ฝๆ•ฐ๏ผš

Scalaไธ้ตๅพชJavaBeansๆ ‡ๅ‡†๏ผŒๅ› ๆญคๆˆ‘ไปฌๅœจ่ฟ™้‡Œๅฑ•็คบ็š„Javaไปฃ็  ไธŽๅฎƒๅŽ้ข็š„Scalaไปฃ็ ็ญ‰ๆ•ˆ๏ผŒ่€Œไธๆ˜ฏๆ˜พ็คบไปฅJavaBeans้ฃŽๆ ผ็ผ–ๅ†™ ็š„Javaไปฃ็ ใ€‚

class Person {
  public String firstName;
  public String lastName;
  public int age;
  public Person(
    String firstName,
    String lastName,
    int age
  ) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }
  public String toString() {
    return String.format("%s %s is %d years old.", firstName, lastName, age);
  }
}
class Person (
  var firstName: String,
  var lastName: String,
  var age: Int
):  
  override def toString = s"$firstName $lastName is $age years old."

่พ…ๅŠฉๆž„้€ ๅ‡ฝๆ•ฐ๏ผš

public class Person {
  public String firstName;
  public String lastName;
  public int age;

  // primary constructor
  public Person(
    String firstName,
    String lastName,
    int age
  ) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }

  // zero-arg constructor
  public Person() {
    this("", "", 0);
  }

  // one-arg constructor
  public Person(String firstName) {
    this(firstName, "", 0);
  }

  // two-arg constructor
  public Person(
    String firstName,
    String lastName
  ) {
    this(firstName, lastName, 0);
  }

}
class Person (
  var firstName: String,
  var lastName: String,
  var age: Int
):
    // zero-arg auxiliary constructor
    def this() = this("", "", 0)

    // one-arg auxiliary constructor
    def this(firstName: String) =
      this(firstName, "", 0)

    // two-arg auxiliary constructor
    def this(
      firstName: String,
      lastName: String
    ) =
      this(firstName, lastName, 0)

end Person

็ฑป้ป˜่ฎคๆ˜ฏๅฐ้—ญ็š„๏ผš

โ€œPlan for inheritance or else forbid it.โ€

final class Person
class Person

ไธบๆ‰ฉๅฑ•ๅผ€ๆ”พ็š„็ฑป๏ผš

class Person
open class Person

ๅ•่กŒๆ–นๆณ•๏ผš

public int add(int a, int b) {
  return a + b;
}
def add(a: Int, b: Int): Int = a + b

ๅคš่กŒๆ–นๆณ•๏ผš

public void walkThenRun() {
  System.out.println("walk");
  System.out.println("run");
}
def walkThenRun() =
  println("walk")
  println("run")

ไธๅฏๅ˜ๅญ—ๆฎต๏ผš

final int i = 1;
val i = 1

ๅฏๅ˜ๅญ—ๆฎต๏ผš

int i = 1;
var i = 1;
var i = 1

ๆŽฅๅฃใ€trait ๅ’Œ็ปงๆ‰ฟ

ๆœฌ่Š‚ๅฐ†JavaๆŽฅๅฃไธŽScala trait ่ฟ›่กŒๆฏ”่พƒ๏ผŒๅŒ…ๆ‹ฌ็ฑปๅฆ‚ไฝ•ๆ‰ฉๅฑ•ๆŽฅๅฃๅ’Œ traitใ€‚

ๆŽฅๅฃ/trait๏ผš

public interface Marker;
trait Marker

็ฎ€ๅ•ๆŽฅๅฃ๏ผš

public interface Adder {
  public int add(int a, int b);
}
trait Adder:
  def add(a: Int, b: Int): Int

ๆœ‰ๅฎžไฝ“ๆ–นๆณ•็š„ๆŽฅๅฃ๏ผš

public interface Adder {
  int add(int a, int b);
  default int multiply(
    int a, int b
  ) {
    return a * b;
  }
}
trait Adder:
  def add(a: Int, b: Int): Int
  def multiply(a: Int, b: Int): Int =
    a * b

็ปงๆ‰ฟ๏ผš

class Dog extends Animal implements HasLegs, HasTail
class Dog extends Animal, HasLegs, HasTail

ๆ‰ฉๅฑ•ๅคšไธชๆŽฅๅฃ

่ฟ™ไบ›ๆŽฅๅฃๅ’Œ็‰นๅพๅ…ทๆœ‰ๅ…ทไฝ“็š„ใ€ๅทฒๅฎž็Žฐ็š„ๆ–นๆณ•๏ผˆ้ป˜่ฎคๆ–นๆณ•๏ผ‰๏ผš

interface Adder {
  default int add(int a, int b) {
    return a + b;
  }
}

interface Multiplier {
  default int multiply (
    int a,
    int b)
  {
    return a * b;
  }
}

public class JavaMath
implements Adder, Multiplier {}

JavaMath jm = new JavaMath();
jm.add(1,1);
jm.multiply(2,2);
trait Adder:
  def add(a: Int, b: Int) = a + b

trait Multiplier:
  def multiply(a: Int, b: Int) = a * b

class ScalaMath extends Adder, Multiplier

val sm = new ScalaMath
sm.add(1,1)
sm.multiply(2,2)

ๆททๆญ๏ผš

N/A
class DavidBanner

trait Angry:
  def beAngry() =
    println("You wonโ€™t like me ...")

trait Big:
  println("Iโ€™m big")

trait Green:
  println("Iโ€™m green")

// mix in the traits as DavidBanner
// is created
val hulk = new DavidBanner with Big with Angry with Green

ๆŽงๅˆถ็ป“ๆž„

ๆœฌ่Š‚ๆฏ”่พƒๅœจ Java ๅ’Œ Scala ไธญ็š„ๆŽงๅˆถ็ป“ๆž„ใ€‚

if ่ฏญๅฅ๏ผŒๅ•่กŒ๏ผš

if (x == 1) { System.out.println(1); }
if x == 1 then println(x)

if ่ฏญๅฅ๏ผŒๅคš่กŒ๏ผš

if (x == 1) {
  System.out.println("x is 1, as you can see:")
  System.out.println(x)
}
if x == 1 then
  println("x is 1, as you can see:")
  println(x)

if, else if, else:

if (x < 0) {
  System.out.println("negative")
} else if (x == 0) {
  System.out.println("zero")
} else {
  System.out.println("positive")
}
if x < 0 then
  println("negative")
else if x == 0
  println("zero")
else
  println("positive")

if ไฝœไธบๆ–นๆณ•ไฝ“๏ผš

public int min(int a, int b) {
  return (a < b) ? a : b;
}
def min(a: Int, b: Int): Int =
  if a < b then a else b

ไปŽ if ่ฟ”ๅ›žๅ€ผ๏ผš

ๅœจ Java ไธญ่ฐƒ็”จ_ไธ‰ๅ…ƒ่ฟ็ฎ—็ฌฆ_๏ผš

int minVal = (a < b) ? a : b;
val minValue = if a < b then a else b

while ๅพช็Žฏ๏ผš

while (i < 3) {
  System.out.println(i);
  i++;
}
while i < 3 do
  println(i)
  i += 1

for ๅพช็Žฏ๏ผŒๅ•่กŒ๏ผš

for (int i: ints) {
  System.out.println(i);
}
//preferred
for i <- ints do println(i)

// also available
for (i <- ints) println(i)

for ๅพช็Žฏ๏ผŒๅคš่กŒ๏ผš

for (int i: ints) {
  int x = i * 2;
  System.out.println(x);
}
for
  i <- ints
do
  val x = i * 2
  println(s"i = $i, x = $x")

for ๅพช็Žฏ๏ผŒๅคš็”Ÿๆˆๅ™จ๏ผš

for (int i: ints1) {
  for (int j: chars) {
    for (int k: ints2) {
      System.out.printf("i = %d, j = %d, k = %d\n", i,j,k);
    }
  }
}
for
  i <- 1 to 2
  j <- 'a' to 'b'
  k <- 1 to 10 by 5
do
  println(s"i = $i, j = $j, k = $k")

ๅธฆๅฎˆๅซ๏ผˆif๏ผ‰่กจ่พพๅผ็š„็”Ÿๆˆๅ™จ๏ผš

List ints =
  ArrayList(1,2,3,4,5,6,7,8,9,10);

for (int i: ints) {
  if (i % 2 == 0 && i < 5) {
    System.out.println(x);
  }
}
for
  i <- 1 to 10
  if i % 2 == 0
  if i < 5
do
  println(i)

for comprehension:

N/A
val list =
  for
    i <- 1 to 3
  yield
    i * 10
// list: Vector(10, 20, 30)

switch/match:

String monthAsString = "";
switch(day) {
  case 1: monthAsString = "January";
          break;
  case 2: monthAsString = "February";
          break;
  default: monthAsString = "Other";
          break;
}
val monthAsString = day match
  case 1 => "January"
  case 2 => "February"
  _ => "Other"

switch/match, ๆฏไธชๆƒ…ๅ†ตไธ‹ๅคšไธชๆกไปถ๏ผš

String numAsString = "";
switch (i) {
  case 1: case 3:
  case 5: case 7: case 9:
    numAsString = "odd";
    break;
  case 2: case 4:
  case 6: case 8: case 10:
    numAsString = "even";
    break;
  default:
    numAsString = "too big";
    break;
}
val numAsString = i match
  case 1 | 3 | 5 | 7 | 9 => "odd"
  case 2 | 4 | 6 | 8 | 10 => "even"
  case _ => "too big"

try/catch/finally:

try {
  writeTextToFile(text);
} catch (IOException ioe) {
  println(ioe.getMessage())
} catch (NumberFormatException nfe) {
  println(nfe.getMessage())
} finally {
  println("Clean up resources here.")
}
try
  writeTextToFile(text)
catch
  case ioe: IOException =>
    println(ioe.getMessage)
  case nfe: NumberFormatException =>
    println(nfe.getMessage)
finally
  println("Clean up resources here.")

้›†ๅˆ็ฑป

ๆœฌ่Š‚ๆฏ”่พƒ Java ๅ’Œ Scala ้‡Œ็š„้›†ๅˆ็ฑปใ€‚

ไธๅฏๅ˜้›†ๅˆ็ฑป

ๅฆ‚ไฝ•ๅˆ›ๅปบไธๅฏๅ˜้›†ๅˆๅฎžไพ‹็š„ไพ‹ๅญใ€‚

Sequences:

List strings = List.of("a", "b", "c");
val strings = List("a", "b", "c")
val strings = Vector("a", "b", "c")

Sets:

Set set = Set.of("a", "b", "c");
val set = Set("a", "b", "c")

Maps:

Map map = Map.of(
  "a", 1,
  "b", 2,
  "c", 3
);
val map = Map(
  "a" -> 1,
  "b" -> 2,
  "c" -> 3
)

ๅฏๅ˜้›†ๅˆ็ฑป

Scala ๅœจๅ…ถ scala.collection.mutable ๅŒ…ไธญๆœ‰ๅฏๅ˜้›†ๅˆ็ฑป๏ผŒไพ‹ๅฆ‚ ArrayBufferใ€Map ๅ’Œ Setใ€‚ ๅœจ ๅฏผๅ…ฅๅฎƒไปฌ ๅˆฐๅฝ“ๅ‰ไฝœ็”จๅŸŸไน‹ๅŽ๏ผŒๅˆ›ๅปบๅฎƒไปฌๅฐฑๅƒๅˆšๅˆšๆ˜พ็คบ็š„ไธๅฏๅ˜ Listใ€Vectorใ€Map ๅ’Œ Set ็คบไพ‹ไธ€ๆ ทใ€‚

Scala ่ฟ˜ๆœ‰ไธ€ไธช Array ็ฑป๏ผŒๆ‚จๅฏไปฅๅฐ†ๅ…ถ่ง†ไธบ Java array ๅŽŸๅง‹็ฑปๅž‹็š„ๅŒ…่ฃ…ๅ™จใ€‚ ไธ€ไธช Scala Array[A] ๆ˜ ๅฐ„ๅˆฐไธ€ไธช Java A[]๏ผŒๆ‰€ไปฅไฝ ๅฏไปฅ่ฎคไธบ่ฟ™ไธชๆ˜ฏ Scala Array[String]๏ผš

val a = Array("a", "b")

่ฟ™ไธช่ฟฝๆบฏๅˆฐ Java ็š„ String[]:

String[] a = {"a", "b"};

ไฝ†ๆ˜ฏ๏ผŒScala Array ่ฟ˜ๅ…ทๆœ‰ๆ‚จๆœŸๆœ›ๅœจ Scala ้›†ๅˆไธญไฝฟ็”จ็š„ๆ‰€ๆœ‰ๅ‡ฝๆ•ฐๆ–นๆณ•๏ผŒๅŒ…ๆ‹ฌ map ๅ’Œ filter๏ผš

val nums = Array(1, 2, 3, 4, 5)
val doubledNums = nums.map(_ * 2)
val ่ฟ‡ๆปคNums = nums.filter(_ > 2)

ๅ› ไธบ Scala Array ็š„่กจ็คบๆ–นๅผไธŽ Java array ็›ธๅŒ๏ผŒๆ‰€ไปฅๆ‚จๅฏไปฅ่ฝปๆพๅœฐๅœจ Scala ไปฃ็ ไธญไฝฟ็”จ่ฟ”ๅ›žๆ•ฐ็ป„็š„ Java ๆ–นๆณ•ใ€‚

ๅฐฝ็ฎก่ฎจ่ฎบไบ† Array๏ผŒไฝ†่ฏท่ฎฐไฝ๏ผŒๅœจ Scala ไธญ้€šๅธธๆœ‰ๅฏ่ƒฝๆ›ด้€‚ๅˆ็š„ Array ๆ›ฟไปฃๅ“ใ€‚ ๆ•ฐ็ป„ๅฏนไบŽไธŽๅ…ถไป–่ฏญ่จ€๏ผˆJavaใ€JavaScript๏ผ‰็š„ไบ’ๆ“ไฝœๅพˆๆœ‰็”จ๏ผŒๅนถไธ”ๅœจ็ผ–ๅ†™้œ€่ฆไปŽๅบ•ๅฑ‚ๅนณๅฐ่Žทๅพ—ๆœ€ๅคงๆ€ง่ƒฝ็š„ไฝŽ็บงไปฃ็ ๆ—ถไนŸๅพˆๆœ‰็”จใ€‚ไฝ†ๆ€ป็š„ๆฅ่ฏด๏ผŒๅฝ“ไฝ ้œ€่ฆไฝฟ็”จๅบๅˆ—ๆ—ถ๏ผŒScala ็š„ไน ๆƒฏ็”จๆณ•ๆ˜ฏๆ›ดๅ–œๆฌขๅƒ Vector ๅ’Œ List ่ฟ™ๆ ท็š„ไธๅฏๅ˜ๅบๅˆ—๏ผŒ็„ถๅŽๅœจไฝ ็œŸ็š„้œ€่ฆๅฏๅ˜ๅบๅˆ—ๆ—ถไฝฟ็”จ ArrayBufferใ€‚

ๆ‚จ่ฟ˜ๅฏไปฅไฝฟ็”จ Scala CollectionConverters ๅฏน่ฑกๅœจ Java ๅ’Œ Scala ้›†ๅˆ็ฑปไน‹้—ด่ฟ›่กŒ่ฝฌๆขใ€‚ ๅœจไธๅŒ็š„ๅŒ…ไธญๆœ‰ไธคไธชๅฏน่ฑก๏ผŒไธ€ไธช็”จไบŽไปŽ Java ่ฝฌๆขไธบ Scala๏ผŒๅฆไธ€ไธช็”จไบŽไปŽ Scala ่ฝฌๆขไธบ Javaใ€‚ ไธ‹่กจๆ˜พ็คบไบ†ๅฏ่ƒฝ็š„่ฝฌๆข๏ผš

Java Scala
java.util.Collection scala.collection.Iterable
java.util.List scala.collection.mutable.Buffer
java.util.Set scala.collection.mutable.Set
java.util.Map scala.collection.mutable.Map
java.util.concurrent.ConcurrentMap scala.collection.mutable.ConcurrentMap
java.util.Dictionary scala.collection.mutable.Map

้›†ๅˆ็ฑป็š„ๆ–นๆณ•

็”ฑไบŽ่ƒฝๅคŸๅฐ† Java ้›†ๅˆ่ง†ไธบๆต๏ผŒJava ๅ’Œ Scala ็Žฐๅœจๅฏไปฅไฝฟ็”จ่ฎธๅคš็›ธๅŒ็š„้€š็”จๅ‡ฝๆ•ฐๆ–นๆณ•๏ผš

  • map
  • filter
  • forEach/foreach
  • findFirst/find
  • reduce

ๅฆ‚ๆžœๆ‚จไน ๆƒฏๅœจ Java ไธญๅฐ†่ฟ™ไบ›ๆ–นๆณ•ไธŽ lambda ่กจ่พพๅผไธ€่ตทไฝฟ็”จ๏ผŒๆ‚จไผšๅ‘็Žฐๅœจ Scala ็š„ ้›†ๅˆ็ฑป ไธŠไฝฟ็”จ็›ธๅŒ็š„ๆ–นๆณ•ๅพˆๅฎนๆ˜“ใ€‚

Scala ไนŸๆœ‰_ๆ•ฐๅไธช_ๅ…ถไป– ้›†ๅˆๆ–นๆณ•๏ผŒๅŒ…ๆ‹ฌ headใ€tailใ€dropใ€takeใ€distinctใ€flatten ็ญ‰็ญ‰ใ€‚ ่ตทๅˆไฝ ๅฏ่ƒฝๆƒณ็Ÿฅ้“ไธบไป€ไนˆไผšๆœ‰่ฟ™ไนˆๅคšๆ–นๆณ•๏ผŒไฝ†ๆ˜ฏๅœจไฝฟ็”จ Scala ไน‹ๅŽไฝ ไผšๆ„่ฏ†ๅˆฐ_ๅ› ไธบ_ๆœ‰่ฟ™ไบ›ๆ–นๆณ•๏ผŒไฝ ๅพˆๅฐ‘้œ€่ฆๅ†็ผ–ๅ†™่‡ชๅฎšไน‰็š„ for ๅพช็Žฏไบ†ใ€‚

๏ผˆ่ฟ™ไนŸๆ„ๅ‘ณ็€ไฝ ไนŸๅพˆๅฐ‘้œ€่ฆ_่ฏป_่‡ชๅฎšไน‰็š„ for ๅพช็Žฏใ€‚ ๅ› ไธบๅผ€ๅ‘ไบบๅ‘˜ๅ€พๅ‘ไบŽๅœจ_่ฏป_ไปฃ็ ไธŠ่Šฑ่ดน็š„ๆ—ถ้—ดๆ˜ฏ_็ผ–ๅ†™_ไปฃ็ ็š„ๅๅ€๏ผŒ่ฟ™ๅพˆ้‡่ฆใ€‚๏ผ‰

ๅ…ƒ็ป„

Java ๅ…ƒ็ป„ๆ˜ฏ่ฟ™ๆ ทๅˆ›ๅปบ็š„๏ผš

Pair<String, Integer> pair =
  new Pair<String, Integer>("Eleven", 11);

Triplet<String, Integer, Double> triplet =
  Triplet.with("Eleven", 11, 11.0);
Quartet<String, Integer, Double,Person> triplet =
  Quartet.with("Eleven", 11, 11.0, new Person("Eleven"));

ๅ…ถไป– Java ๅ…ƒ็ป„ๅ็งฐๆ˜ฏ Quintetใ€Sextetใ€Septetใ€Octetใ€Enneadใ€Decadeใ€‚

Scala ไธญไปปไฝ•ๅคงๅฐ็š„ๅ…ƒ็ป„้ƒฝๆ˜ฏ้€š่ฟ‡ๅฐ†ๅ€ผๆ”พๅœจๆ‹ฌๅทๅ†…ๆฅๅˆ›ๅปบ็š„๏ผŒๅฆ‚ไธ‹ๆ‰€็คบ๏ผš

val a = ("eleven")
val b = ("eleven", 11)
val c = ("eleven", 11, 11.0)
val d = ("eleven", 11, 11.0, Person("Eleven"))

ๆžšไธพ

ๆœฌ่Š‚ๆฏ”่พƒ Java ๅ’Œ Scala ไธญ็š„ๆžšไธพใ€‚

ๅŸบๆœฌๆžšไธพ๏ผš

enum Color {
  RED, GREEN, BLUE
}
enum Color:
  case Red, Green, Blue

ๅ‚ๆ•ฐๅŒ–็š„ๆžšไธพ๏ผš

enum Color {
  Red(0xFF0000),
  Green(0x00FF00),
  Blue(0x0000FF);

  private int rgb;

  Color(int rgb) {
    this.rgb = rgb;
  }
}
enum Color(val rgb: Int):
  case Red   extends Color(0xFF0000)
  case Green extends Color(0x00FF00)
  case Blue  extends Color(0x0000FF)

็”จๆˆทๅฎšไน‰็š„ๆžšไธพๆˆๅ‘˜๏ผš

enum Planet {
  MERCURY (3.303e+23, 2.4397e6),
  VENUS   (4.869e+24, 6.0518e6),
  EARTH   (5.976e+24, 6.37814e6);
  // more planets ...

  private final double mass;
  private final double radius;

  Planet(double mass, double radius) {
    this.mass = mass;
    this.radius = radius;
  }

  public static final double G =
    6.67300E-11;

  private double mass() {
    return mass;
  }

  private double radius() {
    return radius;
  }

  double surfaceGravity() {
    return G * mass /
      (radius * radius);
  }

  double surfaceWeight(
    double otherMass
  ) {
    return otherMass *
      surfaceGravity();
  }

}
enum Planet(
  mass: Double,
  radius: Double
):
  case Mercury extends
    Planet(3.303e+23, 2.4397e6)
  case Venus extends
    Planet(4.869e+24, 6.0518e6)
  case Earth extends
    Planet(5.976e+24, 6.37814e6)
    // more planets ...

  private final val G = 6.67300E-11

  def surfaceGravity =
    G * mass / (radius * radius)

  def surfaceWeight(otherMass: Double)
    = otherMass * surfaceGravity

ๅผ‚ๅธธๅ’Œ้”™่ฏฏๅค„็†

ๆœฌ่Š‚ไป‹็ป Java ๅ’Œ Scala ไธญ็š„ๅผ‚ๅธธๅค„็†ไน‹้—ด็š„ๅทฎๅผ‚ใ€‚

Java ไฝฟ็”จๆฃ€ๆŸฅๅผ‚ๅธธ

Java ไฝฟ็”จๆฃ€ๆŸฅ็š„ๅผ‚ๅธธ๏ผŒๅ› ๆญคๅœจ Java ไปฃ็ ไธญ๏ผŒๆ‚จๅކๆฅ็ผ–ๅ†™่ฟ‡ try/catch/finally ๅ—๏ผŒไปฅๅŠๆ–นๆณ•ไธŠ็š„ throws ๅญๅฅ๏ผš

public int makeInt(String s)
throws NumberFormatException {
  // code here to convert a String to an int
}

Scala ไธไฝฟ็”จๆฃ€ๆŸฅๅผ‚ๅธธ

Scala ็š„ไน ๆƒฏ็”จๆณ•ๆ˜ฏ_ไธ_ไฝฟ็”จ่ฟ™ๆ ท็š„ๆฃ€ๆŸฅๅผ‚ๅธธใ€‚ ๅœจๅค„็†ๅฏ่ƒฝๆŠ›ๅ‡บๅผ‚ๅธธ็š„ไปฃ็ ๆ—ถ๏ผŒๆ‚จๅฏไปฅไฝฟ็”จ try/catch/finally ๅ—ไปŽๆŠ›ๅ‡บๅผ‚ๅธธ็š„ไปฃ็ ไธญๆ•่Žทๅผ‚ๅธธ๏ผŒไฝ†ๆ˜ฏๅฆ‚ไฝ•ไปŽ้‚ฃ้‡Œๅผ€ๅง‹็š„ๆ–นๅผๆ˜ฏไธๅŒ็š„ใ€‚

่งฃ้‡Š่ฟ™ไธ€็‚น็š„ๆœ€ๅฅฝๆ–นๆณ•ๆ˜ฏ่ฏด Scala ไปฃ็ ๆ˜ฏ็”ฑๅ…ทๆœ‰่ฟ”ๅ›žๅ€ผ็š„_่กจ่พพๅผ_็ป„ๆˆ็š„ใ€‚ ๅ…ถ็ป“ๆžœๆ˜ฏ๏ผŒๆœ€็ปˆไฝ ๅ†™ไปฃๅฐฑๅƒๅ†™ไธ€็ณปๅˆ—ไปฃๆ•ฐ่กจ่พพๅผ๏ผš

val a = f(x)
val b = g(a,z)
val c = h(b,y)

่ฟ™ๅพˆๅฅฝ๏ผŒๅฎƒๅชๆ˜ฏไปฃๆ•ฐใ€‚ ๆ‚จๅˆ›ๅปบๆ–น็จ‹ๆฅ่งฃๅ†ณๅฐ้—ฎ้ข˜๏ผŒ็„ถๅŽ็ป„ๅˆๆ–น็จ‹ๆฅ่งฃๅ†ณๆ›ดๅคง็š„้—ฎ้ข˜ใ€‚

้žๅธธ้‡่ฆ็š„ๆ˜ฏโ€”โ€”ๆญฃๅฆ‚ไฝ ๅœจไปฃๆ•ฐ่ฏพ็จ‹ไธญๆ‰€่ฎฐๅพ—็š„้‚ฃๆ ทโ€”โ€”ไปฃๆ•ฐ่กจ่พพๅผไธไผš็Ÿญ่ทฏโ€”โ€”ๅฎƒไปฌไธไผšๆŠ›ๅ‡บไผš็ ดๅไธ€็ณปๅˆ—ๆ–น็จ‹็š„ๅผ‚ๅธธใ€‚

ๅ› ๆญค๏ผŒๅœจ Scala ไธญ๏ผŒๆˆ‘ไปฌ็š„ๆ–นๆณ•ไธไผšๆŠ›ๅ‡บๅผ‚ๅธธใ€‚ ็›ธๅ๏ผŒๅฎƒไปฌ่ฟ”ๅ›žๅƒ Option ่ฟ™ๆ ท็š„็ฑปๅž‹ใ€‚ ไพ‹ๅฆ‚๏ผŒ่ฟ™ไธช makeInt ๆ–นๆณ•ๆ•่Žทไธ€ไธชๅฏ่ƒฝ็š„ๅผ‚ๅธธๅนถ่ฟ”ๅ›žไธ€ไธช Option ๅ€ผ๏ผš

def makeInt(s: String): Option[Int] =
  try
    Some(s.toInt)
  catch
    case e: NumberFormatException => None

Scala Option ็ฑปไผผไบŽ Java Optional ็ฑปใ€‚ ๅฆ‚ๅ›พๆ‰€็คบ๏ผŒๅฆ‚ๆžœ string ๅˆฐ int ็š„่ฝฌๆขๆˆๅŠŸ๏ผŒๅˆ™ๅœจ Some ๅ€ผไธญ่ฟ”ๅ›ž Int๏ผŒๅฆ‚ๆžœๅคฑ่ดฅ๏ผŒๅˆ™่ฟ”ๅ›ž None ๅ€ผใ€‚ Some ๅ’Œ None ๆ˜ฏ Option ็š„ๅญ็ฑปๅž‹๏ผŒๅ› ๆญค่ฏฅๆ–นๆณ•่ขซๅฃฐๆ˜Žไธบ่ฟ”ๅ›ž Option[Int] ็ฑปๅž‹ใ€‚

ๅฝ“ๆ‚จๆœ‰ไธ€ไธช Option ๅ€ผๆ—ถ๏ผŒไพ‹ๅฆ‚ makeInt ่ฟ”ๅ›ž็š„ๅ€ผ๏ผŒๆœ‰ๅพˆๅคšๆ–นๆณ•ๅฏไปฅไฝฟ็”จๅฎƒ๏ผŒๅ…ทไฝ“ๅ–ๅ†ณไบŽๆ‚จ็š„้œ€่ฆใ€‚ ๆญคไปฃ็ ๆ˜พ็คบไบ†ไธ€็งๅฏ่ƒฝ็š„ๆ–นๆณ•๏ผš

makeInt(aString) match
  case Some(i) => println(s"Int i = $i")
  case None => println(s"Could not convert $aString to an Int.")

Option ๅœจ Scala ไธญๅพˆๅธธ็”จ๏ผŒๅฎƒๅ†…็ฝฎๅœจๆ ‡ๅ‡†ๅบ“็š„่ฎธๅคš็ฑปไธญใ€‚ ๅ…ถไป–็ฑปไผผ็š„็ฑป็š„้›†ๅˆ๏ผŒไพ‹ๅฆ‚ Try/Success/Failure ๅ’Œ Either/Left/Right๏ผŒๆไพ›ไบ†ๆ›ดๅคง็š„็ตๆดปๆ€งใ€‚

ๆœ‰ๅ…ณๅœจ Scala ไธญๅค„็†้”™่ฏฏๅ’Œๅผ‚ๅธธ็š„ๆ›ดๅคšไฟกๆฏ๏ผŒ่ฏทๅ‚้˜… ๅ‡ฝๆ•ฐๅผ้”™่ฏฏๅค„็† ้ƒจๅˆ†ใ€‚

Scala ็‹ฌๆœ‰็š„ๆฆ‚ๅฟต

ไปฅไธŠๅฐฑๆ˜ฏ Java ๅ’Œ Scala ่ฏญ่จ€็š„ๆฏ”่พƒใ€‚

Scala ไธญ่ฟ˜ๆœ‰ๅ…ถไป–ไธ€ไบ›ๆฆ‚ๅฟต็›ฎๅ‰ๅœจ Java 11 ไธญๆ˜ฏๆฒกๆœ‰็š„ใ€‚ ่ฟ™ๅŒ…ๆ‹ฌ๏ผš

Contributors to this page: