简体   繁体   English

Kotlin 中 object / 私有构造函数 / 伴侣 object 之间的区别?

[英]Difference between object / private constructor / companion object in Kotlin?

Please don't blame me.请不要怪我。 Im just moving from Java to Kotlin.我刚刚从 Java 移动到 Kotlin。 I'm trying to create a singleton as a regular java way with help of Singleton.getInstance().someMethod() and have found that in Kotlin there are several different things you can use: I'm trying to create a singleton as a regular java way with help of Singleton.getInstance().someMethod() and have found that in Kotlin there are several different things you can use:

Object (separate file) object Singleton Object(单独文件) object Singleton

Companion object companion object Factory {}配套 object companion object Factory {}

Private constructor class Singleton private constructor()私有构造函数class Singleton private constructor()

So can you please help me and explain where we can you what type?所以你能帮我解释一下我们可以在哪里你是什么类型的吗?

object Singleton

  1. Thread safe singleton线程安全 singleton
  2. Not an expression不是表达式
  3. Cannot be used on the right hand side of an assignment statement.不能用于赋值语句的右侧。
  4. Object declaration's initialization is thread-safe and done at first access Object 声明的初始化是线程安全的,并在第一次访问时完成
  5. Can have supertypes可以有超类型
  6. Object declarations can't be local (ie be nested directly inside a function) Object 声明不能是本地的(即直接嵌套在函数内)
  7. Can be nested into other object declarations or non-inner classes可以嵌套到其他 object 声明或非内部类中

companion object Factory {}

  1. Members of the companion object can be called by using simply the class name (hosting companion) as the qualifier伴侣 object 的成员可以通过简单地使用 class 名称(托管伴侣)作为限定符来调用
  2. The name of the companion object can be omitted伴侣object的名称可以省略
  3. Members of companion objects look like static members in other languages, at runtime those are still instance members of real objects伴随对象的成员看起来像其他语言中的 static 成员,在运行时它们仍然是真实对象的实例成员
  4. A companion object is initialized when the corresponding class is loaded (resolved), matching the semantics of a Java static initializer当相应的 class 被加载(已解决)时,伴随的 object 被初始化,匹配 Java ZA8224DF1initializer 的语义

class Singleton private constructor()

I don't think you need that for singleton in kotlin as kotlin already provides good singleton option out of the box, however as stated by other SO user here private constructor is serving the same purpose in kotlin as in, for example, java - to prevent instantiation. I don't think you need that for singleton in kotlin as kotlin already provides good singleton option out of the box, however as stated by other SO user here private constructor is serving the same purpose in kotlin as in, for example, java - to防止实例化。 As a second thought, if you think of creating utils like classes in kotlin, please better consider using extension functions.再想一想,如果您想在 kotlin 中创建类似类的实用程序,请更好地考虑使用扩展函数。

PS.: it should be pretty obvious so I'll mention it - 99% of the above is brutally copy-pasted from https://kotlinlang.org/docs/reference/object-declarations.html - may be it has better chances to be more searchable here:) PS.:这应该很明显,所以我会提到它 - 以上内容的 99% 是从https://kotlinlang.org/docs/reference/object-declarations.html残酷地复制粘贴的 - 也许它有更好的机会在这里更容易搜索:)

If you need a singleton - a class that only has got one instance - you can declare the class in the usual way, but use the object keyword instead of class. If you need a singleton - a class that only has got one instance - you can declare the class in the usual way, but use the object keyword instead of class. If you need a function or a property to be tied to a class rather than to instances of it (similar to @staticmethod in Python), you can declare it inside a companion object.如果您需要 function 或要绑定到 class 而不是它的实例的属性(类似于 Python 中的@staticmethod),您可以在伴随的 ZA8CFDE6331BD59EB2AC96F8911C4B66Z.

Private constructors are used to prevent creating instances of a class when there are no instance fields or methods, such as the Math class, or when a method is called to obtain an instance of a class.当没有实例字段或方法(例如 Math class)或调用方法来获取 class 的实例时,私有构造函数用于防止创建 class 的实例。

Objects in Kotlin are like static classes in Java. Kotlin 中的对象类似于 Java 中的 static 类。 They are usually used to construct the singleton pattern:它们通常用于构造 singleton 模式:

object Singleton

The equivalent in Java would be: Java 中的等效项为:

public static class Singleton{}

The companion object is used in cases (as your companion object name states) where you have to apply the Factory pattern or the static factory pattern. companion object用于必须应用工厂模式或 static 工厂模式的情况(如您的伴侣 object 名称所述)。

Let's suppose we have this in Java:假设我们在 Java 中有这个:

public class Fragment(){
  private Fragment(){}

  public static Fragment newInstance(){
    return new Fragment();
  }
  
}

The equivalent of that in Kotlin would be: Kotlin 中的等价物是:

class Fragment private constructor(){
  companion object{
    fun newInstance() = Fragment()
  }
}

The companion object is also an object but through the word companion is just telling JVM that the one class in which this object is, has access to everything inside it. The companion object is also an object but through the word companion is just telling JVM that the one class in which this object is, has access to everything inside it.

Therefore if you try to call it from Java code, it would be something like this:因此,如果您尝试从 Java 代码中调用它,它将是这样的:

Fragment.Companion.newInstance()

The above example actually also fits for private constructor.上面的例子实际上也适用于私有构造函数。 Basically, even in Java, when you don't need to access the constructor directly, just mark the constructor as private and use a static factory method.基本上,即使在 Java 中,当您不需要直接访问构造函数时,只需将构造函数标记为私有并使用 static 工厂方法即可。

Regarding your question, with the information provided above:关于您的问题,根据上面提供的信息:

To achieve达到

Singleton.getInstance().someMethod()

with exactly this call, you have to do this:正是这个电话,你必须这样做:

class Singleton private constructor(){
  companion object{
    fun getInstance() = Singleton()
    fun someMethod(){ /* Your implement here */}
  }
}

However that's not too sophisticated in Kotlin style.然而,这在 Kotlin 风格中并不太复杂。

Just do:做就是了:

object Singleton{
    fun someMethod(){ /* Your method here */}
}

Then just call it:然后调用它:

Singleton.myMethod()

EDIT: Regarding your question of SharedPreferences I don't suggest to use an object for that.编辑:关于您的SharedPreferences问题,我不建议为此使用object You need the constructor for the context and perhaps shared preferences mode.您需要上下文的构造函数,也许还需要共享首选项模式。 Therefore I would go with something like this (assuming that you are using dagger since you mentioned it in comment):因此我会 go 像这样(假设你使用匕首,因为你在评论中提到它):

class SharedPreferencesHelper @Inject constructor(val context: Context, val mode: Int) // not sure about the mode type but check the docs {

    private lateinit var sharedPreferences: SharedPreferences
    private lateinit var sharedPreferencesEditor: SharedPreferences.Editor

    init{
        sharedPreferences = context.getSharedPreferences("filename", mode)
        sharedPreferencesEditor = sharedPreferences.edit()
    }
    
}

Then you just call it in any constructor you need it.然后你只需在你需要的任何构造函数中调用它。

Or:或者:

class SharedPreferencesHelper private constructor(){
    private lateinit var sharedPreferences: SharedPreferences
    private lateinit var sharedPreferencesEditor: SharedPreferences.Editor
    
    companion object {
        fun startSharedPrefs(context: Context, fileName: String, mode: Int) = SharedPreferencesHelper().apply{
         sharedPreferences = context.getSharedPreferences(fileName, mode)
         sharedPreferencesEditor = sharedPreferences.edit()
        }
    }

}

Then start it in a dagger module:然后在匕首模块中启动它:

@Module
object SharedPrefsModule{
    @Singleton
    @Provides
    fun provideSharedPreferences(application: Application) = 
     SharedPreferencesHelper.startSharedPrefs(application, "fileName", MODE_PRIVATE)

}

Then call the dependency wherever you need it然后在需要的地方调用依赖项

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么Intent构造函数在伴随对象中不可见? 科特林 - Why Intent constructor is invisible in companion object? Kotlin how Unit test methods of Kotlin class with private constructor, companion object and extending another class without mocking - how Unit test methods of Kotlin class with private constructor, companion object and extending another class without mocking 伴侣 object 在 Kotlin 中被过度使用? - companion object are overused in Kotlin? Kotlin 序列化与伴侣 object - Kotlin Serialization with Companion object Java静态方法和Kotlin随播对象有什么区别? 为什么在Andorid数据绑定中出现错误? - What is the difference between Java static method and Kotlin companion object ? Why it is giving error in Andorid Data Binding? 为什么我可以在Kotlin的同伴对象之外访问私人娱乐活动? - Why can I access a private fun outside a companion object in Kotlin? 伴随对象Kotlin JNI中的UnsatisfiedLinkError - UnsatisfiedLinkError in companion object Kotlin JNI 在伴侣对象Kotlin中初始化ImageView - Initialize ImageView in companion Object Kotlin Generics、伴侣 object 和 inheritance 在 kotlin - Generics, companion object, and inheritance in kotlin Kotlin 中类和对象的区别 - Difference between a class and object in Kotlin
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM