2012-03-21 163 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,尽管它们并未实现开箱即用的通用接口。