一般風格的問題。Scala對象和單身人士的興起
隨着我越來越擅長編寫功能代碼,我的更多方法正在變成純粹的功能。我發現很多我的「類」(鬆散的代碼容器)正在成爲免費的狀態。因此我使它們成爲對象而不是類,因爲不需要實例化它們。現在在Java世界裏,擁有一個充滿「靜態」方法的類似乎很奇怪,而且通常只用於「助手」類,就像您在Guava和Commons- *中看到的那樣。
所以我的問題是,在斯卡拉的世界裏,有很多邏輯裏面的「對象」而不是「類」很普通,或者是有另一種優選的習慣用法。
一般風格的問題。Scala對象和單身人士的興起
隨着我越來越擅長編寫功能代碼,我的更多方法正在變成純粹的功能。我發現很多我的「類」(鬆散的代碼容器)正在成爲免費的狀態。因此我使它們成爲對象而不是類,因爲不需要實例化它們。現在在Java世界裏,擁有一個充滿「靜態」方法的類似乎很奇怪,而且通常只用於「助手」類,就像您在Guava和Commons- *中看到的那樣。
所以我的問題是,在斯卡拉的世界裏,有很多邏輯裏面的「對象」而不是「類」很普通,或者是有另一種優選的習慣用法。
正如你在標題中提到的那樣,對象是單例類,而不是你在問題文本中提到的靜態方法類。
還有一些東西使得scala對象比java-world中的靜態和單例更好,所以在scala中使用它們是非常「正常」的。
一方面,不同於靜態方法,對象的方法是多態的,因此您可以輕鬆地將對象作爲依賴關係:
scala> trait Quack {def quack="quack"}
defined trait Quack
scala> class Duck extends Quack
defined class Duck
scala> object Quacker extends Quack {override def quack="QUAACK"}
defined module Quacker
// MakeItQuack expects something implementing Quack
scala> def MakeItQuack(q: Quack) = q.quack
MakeItQuack: (q: Quack)java.lang.String
// ...it can be a class
scala> MakeItQuack(new Duck)
res0: java.lang.String = quack
// ...or it can be an object
scala> MakeItQuack(Quacker)
res1: java.lang.String = QUAACK
這使得他們可以使用沒有緊密結合,並沒有促進全球狀態(這是兩個這些問題通常歸因於靜態方法和單例)。
然後有一個事實,他們取消了所有使單身人士如此醜陋和unidiomatic-看在java中的樣板。在我看來,這是一個經常被忽視的問題,也是單身人士在java中如此不悅的部分原因,即使他們是無國籍人士並且不被用作全球國家。
此外,您必須在所有java單例中重複的樣板文件賦予了類的兩個職責:確保只有一個本身的實例並執行它應該執行的任何操作。 scala具有聲明式的方式來指定某件事是單例式的,這一事實使得班級和程序員免於違反單一責任原則。在scala中,你知道一個對象是一個單例,你可以推理它的功能。
我認爲它不能強調一個scala對象可以擴展任何東西,這是與依賴注入一起使用它的基礎成語。謝謝你舉個例子! –
@ChristianSchlichtherle謝謝,我只是希望我有一個更好的例子。我不喜歡我給的那些人爲的東西...... –
是的,我會說這是正常的。
對於我的大部分類,我創建了一個伴侶對象來處理那裏的一些初始化/驗證邏輯。例如,而不是在構造函數中,如果參數驗證失敗時拋出異常,可以返回在同伴的Option
或Either
對象適用法:
class X(val x: Int) {
require(x >= 0)
}
// ==>
object X {
def apply(x: Int): Option[X] =
if (x < 0) None else Some(new X(x))
}
class X private (val x: Int)
在同伴對象可以增添不少額外的邏輯,如不可變對象的緩存。
對象也是好的實例之間發送信號,如果沒有必要還發送消息:
object X {
def doSomething(s: String) = ???
}
case class C(s: String)
class A extends Actor {
var calculateLater: String = ""
def receive = {
case X => X.doSomething(s)
case C(s) => calculateLater = s
}
}
另一種使用情況的對象是減少元素的範圍:
// traits with lots of members
trait A
trait B
trait C
trait Trait {
def validate(s: String) = {
import validator._
// use logic of validator
}
private object validator extends A with B with C {
// all members of A, B and C are visible here
}
}
class Class extends Trait {
// no unnecessary members and name conflicts here
}
您還可以使用包對象,例如看看scala吧。這裏的數學包對象 https://lampsvn.epfl.ch/trac/scala/browser/scala/tags/R_2_9_1_final/src//library/scala/math/package.scala
等等,如果它們是無狀態的,爲什麼它們甚至是對象而不是簡單的函數? – RonaldBarzell
你不需要把這些功能放在一些東西里面,這是我的問題。我有一堆相關的函數,它們在一個Object中,只是作爲一個容器。這是否被認爲是Scala中的最佳實踐? – monkjack
哦,好的。我誤解了。謝謝你的澄清。 – RonaldBarzell