Kotlinの解析(中)

8363 ワード

前言
前編のKotlinを通していくつかの基本的な変数、方法、関数、クラスなどの基本的な説明を紹介しました.
1.列挙クラスと拡張
1.1列挙クラス
 Kotlinの列挙クラスはJavaと非常に類似しており、クラスの特性を持ち、列挙可能な同型の値のセットを列挙クラス定義とするのが一般的である.列挙ごとにオブジェクトであるため、性能的にも推奨されない可能性があるが、Androidでは注釈で徐々に置き換えられている.この列挙の使用
1.1.1列挙クラスの基本的な使い方
  kotlinでは、列挙タイプはクラスの形で存在するため、列挙クラスとなる
enum class Direction {
NORTH,SOUTH,WEST,EAST
}

1.1.2列挙値指定に対応する数値
enum class Direction private constructor(val d:Int){ 
    SOUTH(1),WEST(2);

    override fun toString(): String {
        return d.toString()
    }
}

fun main(args:Array){
var dir1 : Direction = Direction. SOUTH
var dir2  = Direction. WEST
println(dir1)//    1
println(dir2)//    2
}

1.1.3列挙のその他の拡張
  var dir1 : Direction = Direction. WEST
        Log.i("tag",dir1.name)//    :WEST
        Log.i("tag",dir1.ordinal.toString()) //            1
        Log.i("tag",dir1.toString()) //         
        Log.i("tag",Direction.valueOf("WEST").toString()) //         

//           ,    values   
for(d in Direction.values()){
println(d)
}

1.2拡張
  拡張はKotlinにおいて非常に重要な機能であり、ソースコードなしでクラスにメンバーを追加してもよいし、サブチーム開発の場合、拡張によりモジュールを複数人に分散して開発することもできる
1.2.1拡張ネイティブAPI
Kotlinの原生の集合拡張
//        ?     Kotlin    ,  ,       swap       
fun MutableList.swap(index1:Int ,index2:Int){
            // MutableList    swap   ,               
            var tmp = this[index1]
            this[index1] = this[index2]
            this[index2] = tmp;
        }

val tab = mutableListOf(1,2,3)
        tab.swap(0,2) //            ,        ,  
        Log.i("tag","jihe:  " + tab.toString())//  [3,2,1]


JDK規格の集合クラスArrayListにhellowメソッドを追加
 fun ArrayList.hellow(string: String){
            println(string)
        }

        var list: ArrayList = ArrayList();
        list.add(20)
        list.add(30)
        list.add(40)
        list.add(50)
        list.swap(0,2)//        
        list.hellow("   !!!  ") //             

1.2.2カスタムクラスを拡張する目的が多く、システムクラスを拡張する必要があるほか、自分で作成したクラスも拡張する必要がある場合がありますが、クラスの中で修正したくない場合があります.この機能は互いに優れています.
open class Parent(val va1: Int, val va2: Int) {//  open  ,         
    var mVal1 = va1
    var mVal2 = va2
    fun add() = this.mVal1 + this.mVal2
}

class Child(va1: Int, va2: Int) : Parent(va1, va2) {
    fun sub() = mVal1 - mVal2
}


        fun Parent.log() {
            Log.i("tag", "  :" + "${mVal1} +${mVal2} = ${add()}")
        }

        fun Child.log() {
            Log.i("tag", "  :" + "${mVal1} -${mVal2} = ${sub()}")
        }

        var par1: Parent = Parent(1, 2)
        var par2: Parent = Child(1, 2)
        var chil1: Child = Child(1, 2)

        par1.log()//  :1 +2 = 3
        par2.log()//  :1 +2 = 3
        chil1.log()//  :1 -2 = -1



open class Parent(val va1: Int, val va2: Int) {
    var mVal1 = va1
    var mVal2 = va2
    fun add() = this.mVal1 + this.mVal2
//      ,     ,        
fun log() {
        Log.i("tag", "  :  " + "${mVal1} +${mVal2} = ${add()}")
    }
}


fun Parent.log() {
            Log.i("tag", "  :" + "${mVal1} +${mVal2} = ${add()}")
        }

        fun Child.log() {
            Log.i("tag", "  :" + "${mVal1} -${mVal2} = ${sub()}")
        }

        var par1: Parent = Parent(1, 2)
        var par2: Parent = Child(1, 2)
        var chil1: Child = Child(1, 2)

        par1.log()//  :  1 +2 = 3
        par2.log()//  :  1 +2 = 3
        chil1.log()//  :  1 +2 = 3
 

(1)par 2のインスタンスオブジェクトはChildであるにもかかわらず,拡張メソッドにより親の拡張メソッドは書き換えられていないため,par 2が呼び出すメソッドは親のメソッドである.(2)クラス内部メンバー関数と拡張によって追加されたメンバー関数が競合すると、内部メンバー関数の優先度が高くなり、拡張によって内部メンバー関数を上書きできなくなる
1.2.3拡張付随オブジェクト
class SubClass  {
    companion object {
    }
}

fun  SubClass.Companion.nihao(){
           Log.i("tag","hello word!")
        }

SubClass.nihao();//     ,      
//    ,  
//          

2.データクラスとパッケージ
  データクラスとパッケージはKotlinの2つの特殊なクラスであり、前者はデータと対応する操作を記述するために用いられ、後者は列挙クラスの拡張に相当し、限られたデータを記述するために用いられる.
2.1データクラス
データクラスはKotlinの構文糖であり、Kotlinコンパイラはデータクラスのメンバー関数を自動的に生産し、開発効率を向上させる.
2.1.1データクラスの使用
//       
class User(var name: String, var sex: Int)  {
    var mName = name
    var mSex = sex
    override fun equals(other: Any?): Boolean {
    //  ,         ,     
        if (other is User) {
            if (mName == other.mName && mSex == other.mSex) {
                return true
            }
        } else {
            return false
        }
        return false
    }
    override fun toString(): String {
      //  ,   Java   ,yes,  
        return "User {name = $mName 
sex = $mSex }" } }

上のUserから分かるように、nameとsexだけが必要で、残りは自動的に倒すことができますが、どうすればいいのでしょうか.実はKotlinで提供されています.それはclassの前にdataキーワードをつければいいということです.
data class Student(var name: String) {
    constructor():this("sdfdf")//             
}

var student = Student("xixi")
var student1 = Student("haha")
Log.i("tag", student.toString()); //  :Student(name=xixi)
Log.i("tag", student1.toString());//  : Student(name=haha)
Log.i("tag", student.equals(student1).toString());//  :false

  データクラスと普通のクラスの最大の違いは、データクラスがコンストラクタのパラメータに基づいて自動的に関連するコードを生成できることである.Kotlinでは、同僚が通常のクラスとデータの保存と管理機能を持っている場合は、直接データクラスを使用することをお勧めします.
データクラスを記述する上での注意点(1)マスターコンストラクタの少なくとも1つのパラメータ(2)マスターコンストラクタのパラメータはvar/val(3)データクラスとしてマークしなければならない抽象クラスではなくopenクラス、閉鎖クラス(sealed)クラスまたは内部クラス(inner)マスターコンストラクタはパラメータが必要であるため、パラメータのないマスターコンストラクタが存在する可能性はありません.2つの解決策:(1)プライマリコンストラクタの各パラメータにデフォルト値を付ける
data class User(val name :String="Bill", var age :Int = 10)

(2)パラメータのないコンストラクタを追加し、メインコンストラクタを呼び出すときにデフォルトパラメータを指定する
data class User(var name : String ,var age :Int){
//     
constructor():this("Devin","18")
}

2.1.2データクラスメンバーの解构  データクラスメンバーの解构、ここで肝心な解构、つまり解构、データクラスの中で、属性でデータを表して、これらの属性は同じデータクラスに属して、これらの属性を使うには、まずデータオブジェクトを引用しなければならなくて、ここでの解构はこれらのデータオブジェクトの属性を抽出して、それぞれ単独で変数に値を与えることを指します
  var student = Student("   ")
  val (name) = student
  Log.i("tag", ";;;;;;"+name );//;;;;;;   

2.1.3閉鎖類  閉鎖類もKotlinの文法糖であり、それを列挙の拡張と理解することができ、1つの閉鎖類、前にsealedを使って、任意の複数の字のオブジェクトがあって、閉鎖類の値はこれらの字のオブジェクトだけで、閉鎖類を使うメリットは、主にwhen表達式と協力して、else形式を使う必要はありません
sealed class Icon ()
class Small() : Icon()
class Big() : Icon()

fun eval(icon: Icon) {
        when (icon) {
            is Small -> {
            }
            is Big -> {
            }
        }
    }

var big = Big()
        eval(big)

3.汎用型
3.1汎用ベース
  汎用とは、データ構造を定義する際に、そのデータ構造を使用するまで、特定のデータ型を指定するタイプのプレースホルダのみを指定することです.
class Box(t :T){
    var value = t
}

var box = Box(1)
Log.i("tag", ";;;;;;" + box.value);

3.2型変異
 Kotlin汎用はワイルドカードを提供していないが,代わりにoutとinのキーワード(1)outで宣言された汎用プレースホルダは汎用タイプ値を取得した場所(2)inで宣言された汎用は汎用タイプ値を設定した場所でのみ使用できる.
(1).outキーの使用
abstract class Source< out T> {
   abstract fun NextT(): T
}

fun demo(strs: Source) {
//    ,  T   out    
    val ni: Source = strs
    
}

(1).inキーの使用
abstract class Comparable{
    abstract fun comparaTo(other:T)
}

fun demo (x:Comparable){
//1.0 Double  ,Double Number    
    x.comparaTo(1.0)
    val y: Comparable = x
}

3.3汎用関数
 fun  single(item :T) :T{
        return item
    }

var single = single(1)
 Log.i("tag", ";;;;;;" + single);

3.4汎用拘束
  最も一般的な制約は上界(upper bound)であり、Javaのextendsキーワードと同じであり、指定がなければデフォルトで使用される上界タイプAny?汎用パラメータを定義するカッコ内では、whereを複数で使用する場合、唯一の上界のみを定義できます.
fun  convert(item :T){
}

funclone (list:List,there:T):List where T :Comparable,T:Cloneable{
//.....
}

まとめ
  この章の学習を通じて、列挙類、データ類、閉鎖類、汎用型を理解し、しかも非常に便利な拡張実用的な文法を学び、原生Apiとその他の類の拡張方法のために便利で、比較的に柔軟で便利で、この紙面の知識があなたに少し役に立つことを望んでいる.