主要方法
Scala 3 提供定義可從命令列呼叫的程式的全新方式:方法上的 @main
注解會將此方法轉換為可執行程式。範例
@main def happyBirthday(age: Int, name: String, others: String*) =
val suffix =
age % 100 match
case 11 | 12 | 13 => "th"
case _ =>
age % 10 match
case 1 => "st"
case 2 => "nd"
case 3 => "rd"
case _ => "th"
val bldr = new StringBuilder(s"Happy $age$suffix birthday, $name")
for other <- others do bldr.append(" and ").append(other)
bldr.toString
這將產生一個主程式 happyBirthday
,可像這樣呼叫
> scala happyBirthday 23 Lisa Peter
Happy 23rd birthday, Lisa and Peter
帶有 @main
注解的方法可以在頂層或靜態可存取的物件中撰寫。程式名稱在每種情況下都是方法名稱,不含任何物件前置字。@main
方法可以有任意數量的參數。對於每個參數類型,都必須有一個 scala.util.CommandLineParser.FromString[T]
類型類別的實例,用於將引數字串轉換為所需的參數類型 T
。主方法的參數清單可以結束於重複參數,然後取得命令列上提供的其他所有引數。
從 @main
方法實作的程式會檢查命令列上是否有足夠的引數來填入所有參數,以及引數字串是否可轉換為所需的類型。如果檢查失敗,程式會終止並顯示錯誤訊息。
範例
> scala happyBirthday 22
Illegal command line after first argument: more arguments expected
> scala happyBirthday sixty Fred
Illegal command line: java.lang.NumberFormatException: For input string: "sixty"
Scala 編譯器會從 @main
方法 f
產生程式,如下所示
- 它在找到
@main
方法的封裝中建立一個名為f
的類別 - 這個類別有一個靜態方法
main
,具有通常的簽章。它將Array[String]
作為引數,並傳回Unit
。 - 產生的
main
方法會呼叫方法f
,並使用scala.util.CommandLineParser
物件中的方法轉換引數。
例如,上述的 happyBirthday
方法會產生與下列類別等效的額外程式碼
final class happyBirthday:
import scala.util.CommandLineParser as CLP
<static> def main(args: Array[String]): Unit =
try
happyBirthday(
CLP.parseArgument[Int](args, 0),
CLP.parseArgument[String](args, 1),
CLP.parseRemainingArguments[String](args, 2))
catch
case error: CLP.ParseError => CLP.showError(error)
注意:上述的 <static>
修飾詞表示 main
方法會產生為類別 happyBirthday
的靜態方法。它不適用於 Scala 中的使用者程式。正規的「靜態」成員會使用物件在 Scala 中產生。
@main
方法是建議用於產生可以在 Scala 3 中從命令列呼叫的程式的方案。它們取代了先前將程式寫為具有特殊 App
父類別的物件的方案。在 Scala 2 中,happyBirthday
也可以像這樣寫
object happyBirthday extends App:
// needs by-hand parsing of arguments vector
...
先前依賴於「神奇」DelayedInit
特質的 App
功能不再可用。 App
目前仍以有限的形式存在,但它不支援命令列引數,而且未來將會被棄用。如果程式需要在 Scala 2 和 Scala 3 之間進行交叉建置,建議使用具有 Array[String]
引數的明確 main
方法。