[移動プログラミング]誤字プログラミング-2

16127 ワード

演算子、条件文、繰返し文、null処理メカニズム、関数

コトリンプログラミング


6.演算子


演算子のオーバーロード
-コトリンは、内部上書き演算子の関数を使用して演算を実行します.
package chap03.sec01

/* data class로 Score 클래스 선언
    데이터 클래스는 컴파일러가 equals(), hashCOde(), toString(), copy()
    함수를 자동으로 생성해주기에 데이터 사용이 편함
    - data class 속성은 클래스 이름 다음에 괄호()안에 정의
 */
data class Score(val a: Int, val b: Int) {
    /*클래스 멤버로 plus()함수 재정의
    - 연산자 재정의 시 operator 키워드 사용 */
     operator fun plus(obj2_Score: Score): Score {
         println("obj2_Score: $obj2_Score")
        return Score(a + obj2_Score.a, b+ obj2_Score.b)
     }
}

/* Score 클래스의 확장함수로 times 함수 선언
- 확장함수를 사용하면 클래스를 변경하지 않고 기능을 추가할 수 있음
- 기능을 확장할 클래스를 알려줘야 하므로 함수명 앞에 클래스 참조를 추가해야함 */

operator fun Score.times(obj2_Score: Score):Score {
    return Score(a*obj2_Score.a,b*obj2_Score.b)
}

fun main() {
    val obj1 = Score(10,20)
    val obj2 = Score(30, 40)
    println("${obj1+obj2}")
    println("${obj1*obj2}")
}
----------------------------------
Score(a=40, b=60)
Score(a=300, b=800)
演算子タイプ
1.算術演算子
2.複合割付演算子
3.論理演算子
4.比較演算子
5.in演算子-ain b/a!in b
6.範囲演算子
7.Invoke演算子()演算子
> 코틀린에서는 함수 호출, 클래스의 인스턴스 호출 시 ()연산자 사용
invoke() 함수에 operator 키워드를 지정하여 해당 클래스에 정의 
익명함수나 람다식을 변수에 지정하고 실행할 때 유용하게 사용
package chap03.sec01

fun main() {
    // 1) invoke 하무를 클래스에 선언, invoke 연산자(괄호)로 호출
    val obj1 = Person("손흥민")

    // invoke() 함수 호출은 객체의 인스턴스(참조변수)에 괄호() 붙여 호출
    obj1("010-1234-1234","[email protected]")

    // 2) 익명함수나 람다식을 변수에 할당하고 invoke 연산자(괄호)로 호출
    val v1 = 100
    val v2: () -> Int = {v1 + 100}
    println("v2: ${v2()}")
}
class Person(private val name: String) {
    // invoke() 함수 오버로딩
    operator fun invoke(phone: String, email: String){
        println("$name, $phone, $email")
    }

}
--------
손흥민, 010-1234-1234, [email protected]
v2: 200
  • 型確認演算子(is,!is)
    ->オブジェクトタイプをチェックし、Javaでinstaceof
  • を使用

    7.クラスとオブジェクト


    クラスの宣言と作成者
  • コードでは、クラス宣言はclassキーワードを使用して、独自のメンバー属性とメソッド(メンバー関数)
  • を持つことができます.
    作成者とは?(constructor)
  • クラスは、オブジェクトの作成時にデフォルトで呼び出される関数であり、クラスのインスタンス
  • を様々な方法で作成します.
  • は、1つのプライマリ(プライマリ)作成者および1つ以上のセカンダリ(セカンダリ)作成者を指定することができる
  • コンパイラは、宣言しないときにパラメータがない
  • クラスヘッダーに
  • を自動的に生成します.
    class 클래스명 [constructor](매개변수들) {
    	consturctor(매개변수들) {
        }
    }
    デフォルトコンストラクタ
  • initキーワードで指定できる初期化ブロック
  • 作成者を宣言すると、作成者のパラメータにデフォルト/varタイプを設定できます:Int=4
  • class Friend(var nmae: Sring, var tel: String, var type: Int) {
    	init {
        	this.type = if(type < 4) type else 4 //1:학교,2:회사,3:SNS,4:기타
        }
    }
    name:作成者限定変数var x/varを宣言すると、宣言を同時に初期化できます.
    Javaとは異なり、New演算子xを使用
    obj.name -> . : 参照演算子
    ほじょコンストラクタ
    プロパティとフィールド(field)
    属性:関数またはクラスの外で宣言される最上位変数またはクラスのメンバー変数
    フィールド:関数または{}で宣言された領域変数
    プロパティを取得する場合はfieldを使用します
    属性を変更するにはvalue->fieldに転送します
    遅延初期化-遅延初期化
  • コトリンでは、クラスのプロパティを宣言しながら初期化する必要があります.
  • その後、
  • オブジェクトの情報が表示されると、
  • を同時に初期化することは困難である.
    1)lateinit(遅延初期化)
  • 宣言後、必要に応じて初期化します.そうしないと、Exception
  • が起動します.
  • varと宣言された属性だけで
  • があります.
  • クラスで宣言された属性のみ(デフォルトの作成者には適用されません)
  • Nullableタイプ属性は使用できません
  • ゲートウェイ
  • は使用できません.
    package chap07.sec03
    
    class CustomUser {
        // property 초기화 지연
        lateinit var userID: String
        // lateinit 생략시:Property must be initialized or be abstract
         // val 안됨
    }
    
    fun main() {
        val obj = CustomUser()
    
        //userID property 초기화
        obj.userID = "hyelin"
        println("userID: ${obj.userID}")
    }
    -------
    userID: hyelin
    package chap07.sec03
    
    class Student {
         lateinit var name: String
    
         // name 속성 초기화 함수
         fun initName(_name: String) {
              this.name = _name
         }
    
         // 속성 초기화 여부 check 함수
         fun initCheck() {
              /* 더블클론(::) ==> 프로퍼티 참조(리플렉션)
              * 리플렉션(reflection)? 클래스, 함수, 프로퍼티에 대한 레퍼런스(정보,참조)를
              * 런타임 때 동적으로 분석해 내는 기법
              *
              * 속성 앞에 더블클론 명시 시 속성을 객체로 엑세스하여 객체에 대한 속성 참조 가능
              * if( !::name.isInitalized) ==> if(((Student).this).name == null)
              * isInitalized : 프로퍼티 초기화 여부 검사 API
              * ::name.get(): name의 게터 호출
               */
              if (!::name.isInitialized) println("not initialized") else println("initialized: ${::name.get()}")
         }
    }
    
         fun main() {
              val sony = Student()
    
              //name 초기화 여부 체크
              sony.initCheck()
    
              //name 속성 초기화(지연 초기화) - 이 시점에서 속성 초기화 이루어짐
              sony.initName("손흥민")
    
              // 초기화 없이 name 속성에 접근하면 UninializedPropertyAccessException 발생
              println("name: ${sony.name}")
    
              // name 포기화 여부 check
              sony.initCheck()
         }
    ------------------------------------
    not initialized
    name: 손흥민
    initialized: 손흥민
    package chap07.sec03
    
    data class User(var id: Int, var name: String, var age:Int)
    
    lateinit var user: User
    
    fun main() {
        // 생성자 호출 시점에서 초기화(지연초기화)
        user = User(101,"sonny", 28)
        println("id: ${user.id}, name: ${user.name}, age:${user.age}")
    }
    ------------------
    id: 101, name: sonny, age:28
    2)by lazy(初期化を遅らせ、使用時に初期化)
  • 属性宣言の場合、初期化領域モンドは
  • を定義する.
  • valと宣言された属性だけで
  • があります.
    package chap07.sec03
    // lazy 지연 초기화 - Property
    
    fun main() {
        // account 객체 생성
        val account = Account()
    
        // 사용 시점에 초기화
        println(account.balance) // balance 속성값 초기화
        println("=========================")
        println("account.balance: ${account.balance}") // 이미 초기화된 값 출력
    }
    class Account {
        init {
            println("init block")
        }
        /* by lazy 지연 초기화
        - lazy는 람다식으로 구성되어 lazy 인스턴스의 반환값을 가지는 함수
    
         */
    
        val balance: Int by lazy {
            print("Setting balance: ")
            100000
        }
    }
    -------------------------
    init block
    Setting balance: 100000
    =========================
    account.balance: 100000
    可視性の制限(アクセス制限)
    :最上位要素クラス、インタフェース、関数、属性などおよびそのメンバー要素の使用可能範囲を制限します.
  • private:これらの要素が定義されている場所のみ、トップレベルの要素です.kt内部、クラスメンバーはクラス内部
  • のみ
  • 保護:最上位レベルではXが使用され、クラスメンバーは定義されたクラスおよびそのサブクラスでのみ
  • が使用されます.
  • Internal:コートリン特有の可視性制限昼間、同じモジュール内のみ
  • public:デフォルトでは、可視性の制限が指定されていない場合はPublic
  • です.

    8.継承


    継承
  • コトリンはマルチ継承Xをサポートし、サブクラスは1つのスーパークラスから
  • のみ継承する.
  • デフォルトはAnyクラス(java-java.lang.Object)
  • です.
  • 継承関係はクローン(:)(java-extends)
  • です.
  • サブクラスジェネレータは、スーパークラスの属性
  • を初期化するためにスーパークラスジェネレータを呼び出す必要がある.
  • 通常クラスとして宣言された場合、すべてのクラスはfinalクラスとして宣言されるため、継承できません.したがって、スーパークラスはopenclassとして使用されます.
    open class SuperClass {}
    class Subclass : SuperClass() {}
  • 関数オーバーライド
  • 親クラスで定義されたProtter関数
  • を再定義
  • Openキーワード
  • を追加
  • overrideキーワードとして再定義された関数が自動的に開き、他のサブクラスで再定義できます.
    open class Super{ open fun print() {} }
    class Sub: Super() { override fun print())
  • 特恵
  • サブクラスで親の構成を再定義して使用
    ルール#ルール#
    親クラスのPropertyと同じ名前とタイプ
    親val,子val,var
    親var、子varのみ
    親nullable,子Non-null
  • 親メンバーへのアクセス
  • 子クラスで親定義のメンバーが呼び出された場合super()
    open var x: Int = 10
    open fun somefun() {}
    類Sub:Super(){//継承
    override var x: Int = 20
    override fun someFun() {
    println("Sub..${super.x}")
    }}
  • 親ジェネレータの呼び出し
  • 継承関係では、サブクラスがオブジェクトを作成するときに親の基本ジェネレータ
  • を呼び出す必要があります.
    継承とインテリジェント鋳造
    インテリジェントな角度選択?明示的な宣言なしで自動的にロールを選択
    1) is
    2) as
    抽象クラス
  • サブクラス設計仕様を作成するには、
  • を選択します.
    抽象クラスで定義された
  • サブクラスが持つべき関数および属性
  • サブクラスは無条件に抽象クラスを継承し、
  • を実施する.
    インタフェースの実装とオーバーライド
  • インタフェースは、抽象的な方法
  • を強制的に実施するために使用される.
  • 強制的に実施し、実施対象の行為が
  • と同じであることを確保する
  • インタフェースキーワードとして宣言されます.サブクラスは抽象メソッド
  • を実装する必要があります.
  • インタフェースは、複数の実装可能で汎用的な方法宣言の
  • である.
    オブジェクトオブジェクト
  • オブジェクトは、
  • のモノトーンモードを実装し、インスタンスを1つだけ作成および共有します.
  • オブジェクトは自動的に「初期使用時」を生成し、プログラムが終了する前にこれらの共通コンテンツを使用するために、以降のコードで共通コンテンツを生成し、
  • を効率的に使用する.
    宣言
  • と同時にオブジェクトを作成することも、匿名オブジェクト
  • を作成することもできる.
  • オブジェクト[オブジェクト名]{プロパティ,宣言関数}
  • 単輪実施例練習
    package chap09.sec02
    /* 생산 공장별(한국,미국)로 자동차 시리얼 번호관리(싱글톤패턴)
        1. 생산 공장별로 자동차의 시리얼 번호
        - 자동차가 생산될 때마다 연속된 시리얼 번호 부여
        2. Car 클래스를 추상클래스로 구현 */
    
        class CarSerialNumber2 {
            enum class Country(val label: String) {
                KOREA("한국"), USA("미국")
            }
    
    
            // 한국 공장 싱글턴 - 제품 시리얼 번호
            object KoreanFactoryNo {
                var serialNumber = 0
                    set(value) {
                        field = value
                        println("Current-serial-No(KOREA): $serialNumber")
                    }
    
                fun increaseNumber() {
                    serialNumber++
                }
            }
    
            object UsaFactoryNo {
                var serialNumber = 0
                    set(value) {
                        field = value
                        println("Current-serial-No(USA): $serialNumber")
                    }
    
                fun increaseNumber() {
                    serialNumber++
                }
            }
    
            // Car 추상 클래스
            abstract class Car(country: Country) {
                private val serial: Int
                abstract fun carInfo()
    
                fun printSerial(): String {
                    return "제품 번호 $serial"
                }
    
                init {
                    when (country) {
                        Country.KOREA -> {
                            KoreanFactoryNo.increaseNumber()
                            serial = KoreanFactoryNo.serialNumber
                        }
                        Country.USA -> {
                            UsaFactoryNo.increaseNumber()
                            serial = UsaFactoryNo.serialNumber
                        }
                    }
                }
            }
    
            // Genesis 자동차
            class Genesis(private val country: Country) : Car(country) {
    
                override fun carInfo() {
                    println("이 자동차는 제니시스, ${printSerial()}번 입니다")
                }
            }
    
            class Grandeur(private val country: Country) : Car(country) {
    
                override fun carInfo() {
                    println("이 자동차는 그랜저, ${printSerial()}번 입니다")
                }
            }
        }
    
    fun main() {
        val car1 = CarSerialNumber2.Genesis(CarSerialNumber2.Country.KOREA)
        val car2 = CarSerialNumber2.Genesis(CarSerialNumber2.Country.KOREA)
        val car3 = CarSerialNumber2.Grandeur(CarSerialNumber2.Country.KOREA)
        println()
        val car4 = CarSerialNumber2.Genesis(CarSerialNumber2.Country.USA)
        val car5 = CarSerialNumber2.Grandeur(CarSerialNumber2.Country.USA)
        println()
    
        car3.carInfo()
    
    }
    ------------------------------------
    Current-serial-No(KOREA): 1
    Current-serial-No(KOREA): 2
    Current-serial-No(KOREA): 3
    
    Current-serial-No(USA): 1
    Current-serial-No(USA): 2
    
    이 자동차는 그랜저, 제품 번호 3번 입니다
    
    
    Companion objec(パートナーオブジェクト)
  • の「同伴オブジェクト」キーを使用して、インスタンスに関係なく、クラス名を使用して、同伴オブジェクトのメンバー関数
  • に直接アクセスできます.
    添付オブジェクト
  • は、クラスのインスタンス機能を使用せず、インスタンス間で共通の属性および関数
  • を作成するために使用する.
    package chap09
    
    fun main() {
        // 클래스명.함수명으로 함수 호출
        OuterClass.printMsg()
    }
    class OuterClass {
        companion object Comobj {
            fun printMsg() {
                println("동반 객체의 함수가 호출됨")
            }
        }
    }
    ネストされたクラスワイルドカードクラス
  • ネストクラスワイルドカードクラスは、他のクラスの内部クラス
  • を含む.
  • ネストまたはInnerクラスのメンバーは、それらを含む外部クラスで
  • を使用することができる.
  • ネストされたクラスは、自分の外部クラスを宣言するオブジェクトを作成する必要はありません.Inverクラスは、
  • を使用するには、外部クラスのオブジェクトを作成する必要があります.
  • Innerクラスは外部クラスのメンバーを参照できますが、ネストクラスでは
  • を参照できません.
    data class

  • データ転送のためにデータ転送オブジェクト(DTO)を作成するクラス.論理を実装することなく純粋なデータを表す
    1) equals
    2) hashCode()
    3) toString()
    4)componsentN()
    5)レプリカの自動作成()

  • オブジェクトの作成時に自動的に生成されるデータ表現とメソッドは、デフォルトの作成者パラメータとして宣言されたデータにのみ適用されます.

  • データクラス顧客()フォーマット
  • package chap09.sec02
    
    /*data class*/
    
    data class Customer(val name: String, val age:Int, val tel:String) {
        init {
            println("멤버 속성이 초기화 되었습니다.")
        }
    
        var nationality: String = "KOREA"
        constructor(name: String, age:Int, tel:String, _nationality:String) : this(name,age,tel) {
            nationality = _nationality
        }
    }
    
    fun main() {
        val obj1= Customer("김혜린", 23,"010-9055-1391")
        val obj2= Customer("손흥민", 28,"010-3452-1223")
        val obj3= Customer("남주혁", 31,"010-1234-3312","KOREA")
    
        /* 객체를 println(obj1)로 출력하면, 자동으로 생성된 toStirng()함수가 호출되어
        객체의 모든 속성값이 문자열로 변환된 후 출력
         */
    
        println("obj1: $obj1")
        println("obj2: $obj2")
        println("obj3: $obj3")
    
        println("${obj3.name}의 국적은 ${obj3.nationality}입니다.")
    
        /*자동으로 생성된 equlas()가 호출되어 두 속성값이 같으면 true 반환*/
        println(obj1==obj2)
    
        // 각 객체의 해시코드값을 비교하여 같으면 true
        println(obj1.hashCode()==obj2.hashCode())
        println("obj1.hashcode() : ${obj1.hashCode()} == obj2.hashcode():${obj2.hashCode()}")
    
        // copy()는 변경을 원하는 속성값만 바꾸고, 나머지는 그대로
    
        val obj4 = obj1.copy(tel="010-9999-9999")
        println(obj4)
    
        // === 연산자를 이용하여 참조하는 객체가 같은지 비교
        // obj4, obj1  변수는 서로 다른 객체를 참조하므로 false
        println(obj4===obj1)
    
        /* 객체 디스트럭처링(destructuring): 객체가 가지고 있는 프로퍼티를 개별 변수로 분해
        - 데이터 클래스 구조를 기준으로 각 속성값을 변수로 추출해 주는
        componentN() 함수 자동 생성 후 호출
        - public final String component() {return this.name;}
         */
    
        val (fName, fAge, fTel) = obj1
        println("$fName,$fAge, $fTel")
        
        // 객체 데이터가 많은 경우 분해 --> 모든 객체를 List 목록으로 구성한 후 for문으로 분해
        val customerList = listOf(obj1, obj2, obj3, obj4)
        for ((name, age, tel)in customerList) {
            println("name: $name, age:$age, tel:$tel")
        }
    }
    --------------------------
    멤버 속성이 초기화 되었습니다.
    멤버 속성이 초기화 되었습니다.
    멤버 속성이 초기화 되었습니다.
    obj1: Customer(name=김혜린, age=23, tel=010-9055-1391)
    obj2: Customer(name=손흥민, age=28, tel=010-3452-1223)
    obj3: Customer(name=남주혁, age=31, tel=010-1234-3312)
    남주혁의 국적은 KOREA입니다.
    false
    false
    obj1.hashcode() : -687180302 == obj2.hashcode():144316990
    멤버 속성이 초기화 되었습니다.
    Customer(name=김혜린, age=23, tel=010-9999-9999)
    false
    김혜린,23, 010-9055-1391
    name: 김혜린, age:23, tel:010-9055-1391
    name: 손흥민, age:28, tel:010-3452-1223
    name: 남주혁, age:31, tel:010-1234-3312
    name: 김혜린, age:23, tel:010-9999-9999
    Enumクラス
  • は、限定値を有する定数を列挙定数として定義、条件に応じて定数を選択できる特殊クラス
  • である.
  • enumクラスで定義する各定数は、オブジェクト
  • とみなされる.
  • メソッド:name()、toString()、ordinal()、compareTo()、valueOf()、value
  • package chap09.sec02
    
    //MileageRate interface
    interface MileageRate {
        fun getMileageRate(): Double
    }
    
    // MemberShip enum class 선언(MileageRate 인터페이스 구현)
    enum class Membership(val discountRate: Double): MileageRate{
        // 열거형 상수 선언 - 열거 상수의 속성을 기본자로 선언, 초기값을 ()에 지정
    
        PLATINUM(15.0) {
            override fun getMileageRate(): Double {
                return 10.0
            }
        },
        ROYAL(10.0) {
            override fun getMileageRate(): Double = 7.0
        },
        GOLD(7.0) {
            override fun getMileageRate(): Double = 5.0
        },
        SILVER(5.0) {
            override fun getMileageRate(): Double = 2.5
        },
    }
    
    fun main() {
        println("귀하는 ${Membership.PLATINUM} 고객으로 \n"+
                "할인율은 ${Membership.PLATINUM.discountRate}%이고, " +
                "마일리지 누적율은 ${Membership.PLATINUM.getMileageRate()}%입니다.")
        println()
    
        println(Membership.ROYAL.discountRate)
        println(Membership.GOLD.getMileageRate())
        println(Membership.SILVER)
        println()
    
        // Membership 배열로 생성성
        val membership = Membership.values()
            for (member in membership) {
                println("멤버십: ${member.name}, 할인율: ${member.discountRate}, "+
                "마일리지: ${member.getMileageRate()}")
            }
    }
    ----------------------
    
    귀하는 PLATINUM 고객으로 
    할인율은 15.0%이고, 마일리지 누적율은 10.0%입니다.
    
    10.0
    5.0
    SILVER
    
    멤버십: PLATINUM, 할인율: 15.0, 마일리지: 10.0
    멤버십: ROYAL, 할인율: 10.0, 마일리지: 7.0
    멤버십: GOLD, 할인율: 7.0, 마일리지: 5.0
    멤버십: SILVER, 할인율: 5.0, 마일리지: 2.5