kotlin抽象静态乐趣在伴侣对象

时间:2018-01-11 05:21:20

标签: java static kotlin abstract-class companion-object

我从一个名为UserViewHolder的官方样本中学习了ViewHolder的使用。

public class UserViewHolder extends RecyclerView.ViewHolder {

static UserViewHolder create(LayoutInflater inflater, ViewGroup parent) {
    UserItemBinding binding = UserItemBinding
        .inflate(inflater, parent, false);
    return new UserViewHolder(binding);
  } 

  private UserItemBinding mBinding;

  private UserViewHolder(UserItemBinding binding) {
    super(binding.getRoot());
    mBinding = binding;
  }

  public void bindTo(User user) {
    mBinding.setUser(user);
    mBinding.executePendingBindings();
  }

}

我要写很多ViewHolder个类,所以我希望我能写一个抽象类。在Java中,它看起来像:

public abstract  static class BaseViewHolder {

abstract static BaseViewHolder create()

abstract void bindTo()

}

我尝试使用Kotlin编写它,但最后我发现它并不像Java中那么简单。

abstract class BaseViewHolder(itemView: View):RecyclerView.ViewHolder(itemView) {

abstract fun bindTo(viewModel: BaseViewModel)

}

在Kotlin中,如果我想要一个静态函数,我需要在“伴侣对象”中编写该函数。但它不可能是“抽象的”。

在Java中,带抽象类的抽象类很常见。

但是如何在Kotlin中写出来?

更新

我已经编写了自己的 SleepViewHolder 。我要写很多ViewHolder,比如AppleViewHolder,BananaViewHolder等等。所以我想构建一个 BaseViewHolder 作为模式。我的问题是,在这种情况下,编写模式 BaseViewHolder 的最佳方法是什么?我应该更改它的构成,还是将创建功能公开?

open class SleepViewHolder private constructor(private val binding: ItemSleepBinding)
: RecyclerView.ViewHolder(binding.root) {

companion object {
    @JvmStatic
    fun create(inflater: LayoutInflater, parent: ViewGroup): SleepViewHolder {

        val binding: ItemSleepBinding
                = DataBindingUtil.inflate(inflater, R.layout.fragment_base, parent, false)

        return SleepViewHolder(binding)
    }
}

open fun bindTo(viewmodel: SleepViewModel) {
    binding.vm = viewmodel
    binding.executePendingBindings()
}

}

2 个答案:

答案 0 :(得分:2)

Kotlin中,与Java or C#,类不同,没有静态方法。在大多数情况下,建议只使用包级功能。

如果您需要编写一个可以在没有类实例但需要访问类的内部(例如,工厂方法)的情况下调用的函数,则可以将其作为对象声明的成员写入其中类。

更具体地说,如果在类中声明一个伴随对象,您将能够使用与Java/C#中调用静态方法相同的语法来调用其成员,只使用类名作为限定符。

这是你编写伴侣类的方法

class MyClass {
   companion object { } // will be called "Companion"
}
fun MyClass.Companion.foo() { // ...
}

这就是你如何调用foo()函数......

MyClass.foo()

答案 1 :(得分:0)

默认情况下,嵌套类在Kotlin中为static。因此,您不必在类名之前添加任何修饰符。您可以参考下面提供的示例作为起点。

注意:ItemFruitItemAppleItemBanana的超类

class ExampleAdapter: RecyclerView.Adapter<ExampleAdapter.BaseViewHolder<ItemFruit>>(){

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DynamicSpinnerAdapter.ViewHolder {
        when(viewType){
            VIEW_TYPE_BANANA -> BananaViewHolder(....)  // Inflate your view Banana layout here
            VIEW_TYPE_APPLE  -> AppleViewHolder(....)   // Inflate your view Banana layout here
            else             ->                         // Do something for default case
        }
    }

    override fun onBindViewHolder(holder: BaseViewHolder<ItemFruit>, position: Int){
        holder.bind(itemAppleOrBanana)      // binds your item to corresponding view
    }

    override fun getItemViewType(position: Int): Int {
        return when (position){
            condition_banana -> VIEW_TYPE_BANANA
            condition_apple  -> VIEW_TYPE_BANANA
            else             -> VIEW_TYPE_NONE
        }
    }

    inner class BananaViewHolder(itemView: View): BaseViewHolder<ItemBanana>(itemView) {
        override fun bind(item: ItemBanana) {
            // Implement your logic
        }

    }
    inner class AppleViewHolder(itemView: View): BaseViewHolder<ItemApple>(itemView) {
        override fun bind(item: ItemApple) {
            // Implement your logic
        }

    }
    inner abstract class BaseViewHolder<T>(itemView: View) : RecyclerView.ViewHolder(itemView){

        internal abstract fun bind(item: T)
    }

    internal abstract inner class GenericViewHolder<T>(itemView: View) :
        RecyclerView.ViewHolder(itemView) {

        internal abstract fun bind(item: T, position: Int)
    }
}