摘要靜態方法我讀過此相關的職位,但並沒有很多具體的答案(可憐的語言設計或多或少): Why can't static methods be abstract in Java在斯卡拉
我有點初來乍到斯卡拉的,這是可能的(可能與特質或其他)?
我試圖讓我的基類擴展一個特徵,但是當我真的希望它們被要求在伴隨對象中實現時,子類需要實現抽象靜態方法作爲成員方法。
摘要靜態方法我讀過此相關的職位,但並沒有很多具體的答案(可憐的語言設計或多或少): Why can't static methods be abstract in Java在斯卡拉
我有點初來乍到斯卡拉的,這是可能的(可能與特質或其他)?
我試圖讓我的基類擴展一個特徵,但是當我真的希望它們被要求在伴隨對象中實現時,子類需要實現抽象靜態方法作爲成員方法。
斯卡拉[*]中沒有靜態方法,所以你的問題是沒有意義的。
但是,你可以得到你想要的東西通過與性狀擴展的對象:
scala> trait A { def foo(): Int }
defined trait A
scala> object C extends A { def foo(): Int = 5 }
defined module C
scala> C.foo
res0: Int = 5
這可能你想要做什麼。沒有任何辦法可以迫使某個類在同伴對象中實現。伴隨對象可能不存在。
[*]從技術上講,這是一個實現細節,而不是整體理念。請參閱Method in companion object compiled into static methods in scala?
實際上,comanion對象的方法可以看作是類的靜態方法。 – Nicolas 2012-03-21 10:58:45
@Nicolas是的,在這個類中有一個靜態轉發器,但正如我所說的,這更像是一個實現細節,以幫助與Java互操作。Scala語言本身沒有靜態方法的概念。它更像是一個單身人士。 – 2012-03-21 11:52:13
陪伴對象不存在的可能性如何?在編譯期間不應該這樣做嗎? – 2012-03-21 22:58:02
有兩種可能的解釋爲什麼抽象靜態方法在Scala,Java,C++或C#中是不可能的。
首先是技術性的:抽象/虛擬方法需要引用一個對象(稱爲這個)來選擇一個將要運行的覆蓋。當你調用一個靜態方法時,你不提供這樣的對象。
其次是邏輯:抽象/虛擬靜態方法沒有任何意義。當你調用一個靜態方法時,你總是知道包含該方法的類型。你寫:
MyClass.DoSomething(args)
如果你有一個擴展MyClass的MyDerivative,你可以定義另一個靜態方法:
MyDerivative.DoSomethingDifferent(args)
有靜態虛擬方法只是沒有意義的,因爲他們的工作只是作爲普通的靜態方法。
通過「抽象靜態方法」,人們通常意味着必須由任何具體子類靜態實現的方法。雖然我同意它的形狀不好,但它們存在的論點是有效的。例如,請參閱scala集合如何嘗試使用「stndard methods」強制創建伴隨對象。 – Nicolas 2012-03-21 11:02:30
我不確定你想用java中的抽象靜態方法做什麼,但是我曾經見過的唯一潛在的用例(我希望我記得誰......)一個直接在泛型類型參數上的方法。
即如果允許的java像這樣...
// this is not valid java...
// let's pretend we can define a static method in an interface
interface Foo {
static String Foo();
}
// a class that implements our interface
class FooImpl implements Foo {
public static String Foo() {return "foo";}
}
...我們可以使用它在一個通用的參數,直接調用foo()的類型
static <T extends Foo> String Test() {
return T.Foo(); // even if our hypothetical static interface
// was a valid thing, this would probably still fail
// due to type erasure
}
這將使有點更有意義在C#中,因爲:
基本上這意味着在「假裝C#」與靜態接口,你可以使用somethi ng對應於上面的「假裝java」代碼來編寫一種通用方法,該方法適用於定義特定運算符(例如,特定運算符)的任何類型。一切都有一個「+」運算符)。
現在回到scala。 scala如何解決這種情況? 部分它沒有。 Scala沒有靜態方法:一個對象是一個單例(即只有一個實例的類),但仍然是一個具有普通實例方法的類,即在仍然只調用方法的對象上,而不是直接在類型上甚至運算符都是scala中的方法)。
所以在斯卡拉可以這樣寫:
trait Foo { def Foo:String }
object FooImpl extends Foo { def Foo = "foo" }
def Test(f: Foo) = f.Foo
...並調用我們的方法與
scala> Test(FooImpl)
res0: String = foo
// note that FooImpl is still an instance (the only one) of FooImpl and not
// the type itself
你可以做一些技巧與implicits避免將唯一的實例作爲參數:
implicit def aFoo = FooImpl
def Test2(implicit f: Foo) = f.Foo
現在這個工程:
scala> Test2
res1: String = foo
使用帶有隱含的更高級技巧,scala還定義了Numeric,即allows you to use operators on any numeric value,儘管它們並未實現開箱即用的通用接口。
你能告訴我們更多關於你的具體情況嗎?爲什麼你需要將該方法放在伴侶對象中?在scala中可能有不同的方式。 – 2012-03-21 13:48:33
下面是一個例子: 我的基本抽象類有一個抽象的自動更正方法,這不需要綁定到特定的實例。我正在考慮在基本抽象類中使用此自動更正方法的方法。如果該功能不需要在子類中重寫,那麼我的子類將需要實現自己的自動更正方法 - 因此抽象靜態方法。 – 2012-03-21 22:55:39
如果您所做的只是調用未綁定到特定實例的方法,則將該方法放在伴隨對象中,然後從您的類和所有子類中調用它。這將是在Scala中正常使用它的方法。 – 2012-03-21 23:13:48