2012-03-21 164 views
6

摘要靜態方法我讀過此相關的職位,但並沒有很多具體的答案(可憐的語言設計或多或少): Why can't static methods be abstract in Java在斯卡拉

我有點初來乍到斯卡拉的,這是可能的(可能與特質或其他)?

我試圖讓我的基類擴展一個特徵,但是當我真的希望它們被要求在伴隨對象中實現時,子類需要實現抽象靜態方法作爲成員方法。

+1

你能告訴我們更多關於你的具體情況嗎?爲什麼你需要將該方法放在伴侶對象中?在scala中可能有不同的方式。 – 2012-03-21 13:48:33

+0

下面是一個例子: 我的基本抽象類有一個抽象的自動更正方法,這不需要綁定到特定的實例。我正在考慮在基本抽象類中使用此自動更正方法的方法。如果該功能不需要在子類中重寫,那麼我的子類將需要實現自己的自動更正方法 - 因此抽象靜態方法。 – 2012-03-21 22:55:39

+0

如果您所做的只是調用未綁定到特定實例的方法,則將該方法放在伴隨對象中,然後從您的類和所有子類中調用它。這將是在Scala中正常使用它的方法。 – 2012-03-21 23:13:48

回答

4

斯卡拉[*]中沒有靜態方法,所以你的問題是沒有意義的。

但是,你可以得到你想要的東西通過與性狀擴展的對象:

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?

+2

實際上,comanion對象的方法可以看作是類的靜態方法。 – Nicolas 2012-03-21 10:58:45

+2

@Nicolas是的,在這個類中有一個靜態轉發器,但正如我所說的,這更像是一個實現細節,以幫助與Java互操作。Scala語言本身沒有靜態方法的概念。它更像是一個單身人士。 – 2012-03-21 11:52:13

+0

陪伴對象不存在的可能性如何?在編譯期間不應該這樣做嗎? – 2012-03-21 22:58:02

0

有兩種可能的解釋爲什麼抽象靜態方法在Scala,Java,C++或C#中是不可能的。

首先是技術性的:抽象/虛擬方法需要引用一個對象(稱爲這個)來選擇一個將要運行的覆蓋。當你調用一個靜態方法時,你不提供這樣的對象。

其次是邏輯:抽象/虛擬靜態方法沒有任何意義。當你調用一個靜態方法時,你總是知道包含該方法的類型。你寫:

MyClass.DoSomething(args) 

如果你有一個擴展MyClass的MyDerivative,你可以定義另一個靜態方法:

MyDerivative.DoSomethingDifferent(args) 

有靜態虛擬方法只是沒有意義的,因爲他們的工作只是作爲普通的靜態方法。

+5

通過「抽象靜態方法」,人們通常意味着必須由任何具體子類靜態實現的方法。雖然我同意它的形狀不好,但它們存在的論點是有效的。例如,請參閱scala集合如何嘗試使用「stndard methods」強制創建伴隨對象。 – Nicolas 2012-03-21 11:02:30

0

我不確定你想用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#中,因爲:

  1. 具體化泛型意味着類型不將被刪除
  2. 在C#運營商靜態方法,你可以define your own operators

基本上這意味着在「假裝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,儘管它們並未實現開箱即用的通用接口。