在Kotlin中是否可以创建一个适用于多个伴生对象的全局通用函数?

huangapple go评论99阅读模式
英文:

Is it possible to make a global, generic function for multiple companion objects in kotlin

问题

I develop an app in Kotlin that has many Activities. 多个Activities的Kotlin应用程序

Most of the navigation is just basic, starting the new activity, not passing anything to the intent. 大多数导航都很基本,只是启动新的活动,不传递任何内容到意图中。

For a few groups of Activities I might pass flags, which is also repetitive throughout my project (e.g. 5 Activities that set intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK). 对于一些Activity组,我可能会传递标志,这在我的项目中也是重复的(例如,设置intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK的5个Activities)。

So if I could find a way to make that just one implementation would make things a little nicer. 所以如果我能找到一种方法,使这只有一个实现将会使事情变得更加美好。

To make things easier and a little neater, I have created companion objects for the Activities that hold the following function: 为了使事情变得更容易和更整洁,我为Activities创建了伴随对象,其中包含以下函数:

  1. companion object {
  2. fun startActivity(context: Context) {
  3. context.startActivity(
  4. Intent(context, MyActivity::class.java)
  5. )
  6. }
  7. }
  8. ... ```
  9. Other classes can simply call `MyActivity.startActivity(context)`. 其他类可以简单地调用`MyActivity.startActivity(context)`。
  10. The function is pretty basic and the only difference between the implementation in different Activities is obviously the `MyActivity::class.java`-part. 这个函数非常基础,不同Activities中的实现唯一的区别显然是`MyActivity::class.java`部分。
  11. So I'd like to know if it's possible to declare this function only ONCE and somehow use it within multiple companion objects for the different activities. 所以我想知道是否可以只声明此函数一次,然后在不同活动的多个伴随对象中以某种方式使用它。
  12. Now, I understand I could do something like this: 现在,我明白我可以这样做:
  13. I define an object that has a function with a generic type and set it up like this: 我定义一个具有泛型类型的对象,并设置如下:
  14. ``` object MyObject {
  15. inline fun <reified T: AppCompatActivity>startActivity(context: Context) {
  16. context.startActivity(
  17. Intent(context, T::class.java)
  18. )
  19. }
  20. }
  21. class MyActivity() : AppCompatActivity() {
  22. companion object {
  23. fun start(context: Context) = MyObject.startActivity<MyActivity>(context)
  24. }
  25. } ```
  26. But this still seems a little hacky. 但这仍然似乎有点巧妙。
  27. What I'm looking for is something like inheritance or an implemented version of an interface to simply add to my companion object. 我在寻找的是类似继承或接口的实现版本,只需添加到我的伴随对象即可。
  28. Something like: 例如:
  29. ``` companion object : MyObject<MyActivity>
  30. // Assuming I can somehow put the generic parameter into the object declaration instead of the function or do something similar

or 或者

  1. import MyObject.startActivity<MyActivity>
  2. } ```
  3. The first option would be especially useful, as it would automatically set up multiple functions of `MyObject` for `MyActivity`. 第一个选项特别有用,因为它会自动为`MyActivity`设置多个`MyObject`函数。
  4. Is something like this even possible? 这样的东西是否可能?
  5. <details>
  6. <summary>英文:</summary>
  7. I develop an app in Kotlin that has many `Activities`. Most of the navigation is just basic, starting the new activity, not passing anything to the intent. For a few groups of Activities I might pass flags, which is also repetitive throughout my project (e.g. 5 Activities that set `intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK`). So if I could find a way to make that just one implementation would make things a little nicer.
  8. To make things easier and a little neater, I have created companion objects for the `Activities` that hold the following function:

class MyActivity: AppCompatActivity() {
companion object {
fun startActivity(context: Context) {
context.startActivity(
Intent(context, MyActivity::class.java)
)
}
}
...

  1. Other classes can simply call `MyActivity.startActivity(context)`.
  2. The function is pretty basic and the only difference between the implementation in different Activities is obviously the `MyActivity::class.java`-part. So id like to know if its possible to declare this function only ONCE and somehow use it within multiple companion objects for the different activities.
  3. Now, I understand I could do something like this:
  4. I define an object that has a function with a generic type and set it up like this:

object MyObject {
inline fun <reified T: AppCompatActivity>startActivity(context: Context) {
context.startActivity(
Intent(context, T::class.java)
)
}
}

class MyActivity() : AppCompatActivity() {
companion object {
fun start(context: Context) = MyObject.startActivity<MyActivity>(context)
}
}

  1. But this still seems a little hacky. What I&#39;m looking for is something like inheritance or an implemented version of an interface to simply add to my companion object. Something like:

companion object : MyObject<MyActivity>
// Assuming I can somehow put the generic parameter into the object declaration instead of the function or do something similar

  1. or

companion object {
import MyObject.startActivity<MyActivity>
}

  1. The first option would be especially useful, as it would automatically set up multiple functions of `MyObject` for `MyActivity`. Is something like this even possible?
  2. </details>
  3. # 答案1
  4. **得分**: 1
  5. 只需扩展函数。
  6. 内联函数 <reified T: AppCompatActivity> Activity.startActivity() {
  7. startActivity(Intent(this, T::class.java))
  8. }
  9. 如果需要额外配置,可以传递 lambda
  10. 内联函数 <reified T: AppCompatActivity> Activity.startActivity(intentConfiguration: Intent.() -> Unit) {
  11. startActivity(Intent(this, T::class.java).apply(intentConfiguration))
  12. }
  13. <details>
  14. <summary>英文:</summary>
  15. You don&#39;t even need a companion, just an extension function.
  16. inline fun &lt;reified T: AppCompatActivity&gt; Activity.startActivity() {
  17. startActivity(Intent(this, T::class.java))
  18. }
  19. If you need additional configuration, you can pass a lambda.
  20. inline fun &lt;reified T: AppCompatActivity&gt; Activity.startActivity(intentConfiguration: Intent.() -&gt; Unit) {
  21. startActivity(Intent(this, T::class.java).apply(intentConfiguration))
  22. }
  23. </details>
  24. # 答案2
  25. **得分**: 1
  26. Companion objects can inherit from other classes. Just make a base implementation somewhere:
  27. 伴随对象可以继承自其他类。只需在某处创建基本实现:
  28. abstract class ActivityCompanion&lt;T: Activity&gt;(val activityClass : Class&lt;T&gt;) {
  29. fun startActivity(context: Context) {
  30. context.startActivity(Intent(context, activityClass))
  31. }
  32. /** rest of functions that reference activityClass **/
  33. }
  34. And inherit it in your companions:
  35. 并在您的伴随对象中继承它:
  36. class MyActivity() : AppCompatActivity() {
  37. companion object : ActivityCompanion&lt;MyActivity&gt;(MyActivity::class.java)
  38. }
  39. It is a little verbose but that's just how generics work.
  40. 这有点冗长,但这就是泛型的工作方式。
  41. <details>
  42. <summary>英文:</summary>
  43. Companion objects can inherit from other classes. Just make a base implementation somewhere:
  44. abstract class ActivityCompanion&lt;T: Activity&gt;(val activityClass : Class&lt;T&gt;) {
  45. fun startActivity(context: Context) {
  46. context.startActivity(Intent(context, activityClass))
  47. }
  48. /** rest of functions that reference activityClass **/
  49. }
  50. And inherit it in your companions:
  51. class MyActivity() : AppCompatActivity() {
  52. companion object : ActivityCompanion&lt;MyActivity&gt;(MyActivity::class.java)
  53. }
  54. It is a little verbose but that&#39;s just how generics work.
  55. </details>
  56. # 答案3
  57. **得分**: 0
  58. 只想指出,更简洁的语法是使用`Context`上的一个具体化扩展函数来完成这个操作。而且你也不需要担心伴生对象。
  59. ```kotlin
  60. inline fun <reified T: Activity> Context.startActivity() =
  61. startActivity(Intent(this, T::class.java))
  62. //用法示例:
  63. someViewOrActivity.startActivity<MyActivity>()

这也在语义上更合理。一个Context启动一个活动。一个Activity不会启动自己。

英文:

Just want to point out that a more concise syntax would be to do this with a reified extension function on Context. And you wouldn't need to worry about companion objects either.

  1. inline fun &lt;reified T: Activity&gt; Context.startActivity() =
  2. startActivity(Intent(this, T::class.java))
  3. //Usage:
  4. someViewOrActivity.startActivity&lt;MyActivity&gt;()

It also semantically makes more sense. A Context starts an activity. An Activity doesn't start itself.

huangapple
  • 本文由 发表于 2020年8月12日 20:11:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/63376269.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定