伴随对象可以实现接口的可能性

时间:2017-12-04 09:50:11

标签: scala kotlin companion-object kotlin-companion

为什么Kotlin / Scala伴随对象可以实现某些接口,这有什么好处?何时使用此功能很有用?

3 个答案:

答案 0 :(得分:3)

因为companion objectobject s,object可以实现接口(或扩展类),并且没有充分的理由不允许它companion object特别

Scala的一个常见用途是工厂:例如SeqListVector等协作对象都扩展TraversableFactory,因此您可以编写使用TraversableFactory的代码并传递其中任何一个来构造类型你要。 E.g。

def build[CC[X] <: Traversable[X] with GenericTraversableTemplate[X, CC], A](factory: TraversableFactory[CC])(elems: A*) = factory(elems)

// build(List)(1,2,3) == List(1, 2, 3)
// build(Set)(1,2,3) == Set(1, 2, 3)

类似地,所有案例类伴随对象都扩展了函数类型。

答案 1 :(得分:1)

当您在程序中只需要一个特定类的实例时,可以使用单例对象。

E.g。 Scala的Nil实现Nil。而不是每种类型的列表都可以实现它的特定 implicit object,而只有其中一种。

typeclass pattern中,您只有一个public static Something用于相应的实施。

此外,如果您在Java中创建object Blah extends Renderable,则可以在随播广告对象中创建该广告。

我个人认为它们对于实现sbt插件很有用,它会将blah.html呈现给文件 customViewHolder.increase.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Double rate=Double.parseDouble(customViewHolder.total.getText().toString()); Log.e("rate",rate+""); Double newrate=rate-((Double.parseDouble(feedItem.getRate())-Double.parseDouble(feedItem.getDiscount()))*(minteger-1)); Log.e("minusval",""+((Double.parseDouble(feedItem.getRate())-Double.parseDouble(feedItem.getDiscount()))*(minteger-1))); Double ratetext=newrate+(Double.parseDouble(feedItem.getRate())-Double.parseDouble(feedItem.getDiscount()))*minteger; Log.e("ratetext",ratetext+""); Double discrate=Double.parseDouble(customViewHolder.disctotal.getText().toString()); Double newdiscrate=discrate-(Double.parseDouble(feedItem.getDiscount())*(minteger-1)); Double disctext=newdiscrate+Double.parseDouble(feedItem.getDiscount())*minteger; Log.e("ratettttttttext",ratetext+""); customViewHolder.total.setText(""+ratetext);// not working ustomViewHolder.totalnew.setText(ratetext+"");// not working customViewHolder.disctotal.setText(disctext+"");// not working } }); 。详细了解有用性here。我必须知道它实现了这个特性!

答案 2 :(得分:1)

您可以将companion object和继承用于某种级别的类级别或静态多态性。

示例1:工厂

考虑一个界面

interface Factory<T> {
    fun create(): T
}

现在,我们创建一个其伴侣对象实现它的类

class Foo {
    companion object: Factory<Foo> {
        override fun create() = Foo()
    }
}

现在我们可以为所有工厂创建一个扩展功能,例如记录对象。

fun <T> Factory<T>.createAndLog(): T {
    val t = create()
    println(t)
    return t
}

不要像这样使用

Foo.createAndLog()

示例2:查询

考虑标记界面

interface Queryable<T>

我们现在有两个类UserArticle,它们代表companion object实现接口的数据库中的表。

class User(val id: String) {
    companion object: Queryable<User> {}
}

class Article(val authorId: String) {
    companion object: : Queryable<Article> {}
}

我们现在可以定义一个扩展函数来从类

创建查询
fun <T> Queryable<T>.query() = db.createQuery<T>()

我们可以称之为

User.query()
//or
Article.query()