├── .gitignore
├── .idea
├── .gitignore
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── kotlinc.xml
├── libraries
│ └── KotlinJavaRuntime.xml
├── misc.xml
├── modules.xml
└── vcs.xml
├── belajar-kotlin-generic.iml
└── src
├── app
├── ComparableInterface.kt
├── Contravariant.kt
├── Covariant.kt
├── GenericClass.kt
├── GenericConstraint.kt
├── GenericExtentionFunction.kt
├── GenericFunction.kt
├── Invariant.kt
├── ObservableProperty.kt
├── ReadOnlyProperty.kt
├── ReadWriteProperty.kt
├── StarProjection.kt
├── TypeErasure.kt
└── TypeProjection.kt
└── data
├── Fruit.kt
├── Function.kt
└── MyData.kt
/.gitignore:
--------------------------------------------------------------------------------
1 | out
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/libraries/KotlinJavaRuntime.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/belajar-kotlin-generic.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/app/ComparableInterface.kt:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | import data.Fruit
4 |
5 | fun main() {
6 | val fruit1 = Fruit("Apple", 100)
7 | val fruit2 = Fruit("Apple", 10)
8 |
9 | println(fruit1 > fruit2)
10 | println(fruit1 >= fruit2)
11 | println(fruit1 < fruit2)
12 | println(fruit1 <= fruit2)
13 | }
--------------------------------------------------------------------------------
/src/app/Contravariant.kt:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | class Contravariant{
4 | fun sayHello(param: T){
5 | println("Hello $param")
6 | }
7 |
8 | // tidak boleh
9 | // fun getData():T {
10 | // return data
11 | // }
12 | }
13 |
14 | fun main() {
15 | val contravariantAny = Contravariant()
16 | val contravariantString: Contravariant = contravariantAny
17 |
18 | // contravariantString.getData() // error
19 | contravariantString.sayHello("Eko")
20 | }
--------------------------------------------------------------------------------
/src/app/Covariant.kt:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | class Covariant(val data: T) {
4 |
5 | fun data(): T {
6 | return data
7 | }
8 |
9 | // tidak boleh membuat function dengan input generic covariant
10 | // fun setData(param: T){
11 | // data = param
12 | // }
13 |
14 | }
15 |
16 | fun main() {
17 | val covariantString = Covariant("Eko")
18 | val covariantAny: Covariant = covariantString
19 |
20 | println(covariantAny.data())
21 |
22 | // covariantAny.setData(100) tidak boleh
23 | }
--------------------------------------------------------------------------------
/src/app/GenericClass.kt:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | import data.MyData
4 |
5 | fun main() {
6 | val myDataString: MyData = MyData("Eko", 100)
7 | myDataString.printlnData()
8 |
9 | val myDataInt = MyData(100, "Eko")
10 | myDataInt.printlnData()
11 | }
--------------------------------------------------------------------------------
/src/app/GenericConstraint.kt:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | interface CanSayHello {
4 | fun sayHello(name: String)
5 | }
6 |
7 | open class Employee
8 |
9 | class Manager : Employee()
10 |
11 | class VicePresident : Employee(), CanSayHello {
12 | override fun sayHello(name: String) {
13 | println("Hello $name, I'm vice president")
14 | }
15 | }
16 |
17 | class Company(val employee: T) where T : Employee, T : CanSayHello
18 |
19 | fun main() {
20 | // val data1 = Company(Employee()) // error CanSayHello
21 | // val data2 = Company(Manager()) //error CanSayHello
22 | val data3 = Company(VicePresident())
23 | // val data4 = Company("String") // error not Employee
24 | }
--------------------------------------------------------------------------------
/src/app/GenericExtentionFunction.kt:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | class Data(val data: T)
4 |
5 | fun Data.print(){
6 | val data: String = this.data
7 | println(data)
8 | }
9 |
10 | fun Data.printInt(){
11 | val data: Int = this.data
12 | println(data)
13 | }
14 |
15 | fun main() {
16 | val data1 = Data(1)
17 | val data2 = Data("Eko")
18 |
19 | // data1.print() // error
20 | data2.print()
21 | data1.printInt()
22 | }
--------------------------------------------------------------------------------
/src/app/GenericFunction.kt:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | import data.Function
4 |
5 | fun main() {
6 | val function = Function("Eko")
7 |
8 | function.sayHello("Joko")
9 | function.sayHello("Joko")
10 |
11 | function.sayHello(10)
12 | function.sayHello(10)
13 | }
--------------------------------------------------------------------------------
/src/app/Invariant.kt:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | class Invariant(var data: T)
4 |
5 | fun main() {
6 | val invariantString = Invariant("String")
7 |
8 | // val invariantAny: Invariant = invariantString // bisa
9 | // invariantAny.data = 100 // bahaya
10 | }
--------------------------------------------------------------------------------
/src/app/ObservableProperty.kt:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | import kotlin.properties.Delegates
4 | import kotlin.properties.ObservableProperty
5 | import kotlin.reflect.KProperty
6 |
7 | class LogObservableProperty(param: T) : ObservableProperty(param){
8 |
9 | override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean {
10 | println("Before change ${property.name} from $oldValue to $newValue")
11 | return true
12 | }
13 |
14 | override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) {
15 | println("After change ${property.name} from $oldValue to $newValue")
16 | }
17 |
18 | }
19 |
20 | class Car(brand: String, year: Int){
21 | var brand: String by LogObservableProperty(brand)
22 | var year: Int by LogObservableProperty(year)
23 | var owner: String by Delegates.notNull()
24 | var description: String by Delegates.vetoable(""){ property, oldValue, newValue ->
25 | println("Before change ${property.name} from $oldValue to $newValue")
26 | true
27 | }
28 | var other: String by Delegates.observable(""){ property, oldValue, newValue ->
29 | println("After change ${property.name} from $oldValue to $newValue")
30 | }
31 | }
32 |
33 | fun main() {
34 | var car = Car("Toyota", 2019)
35 |
36 | car.brand = "Wuling"
37 | println(car.brand)
38 |
39 | car.year = 2020
40 | println(car.year)
41 |
42 | car.owner = "Eko"
43 | println(car.owner)
44 |
45 | car.description = "Desc"
46 | println(car.description)
47 |
48 | car.other = "Other"
49 | println(car.other)
50 |
51 | }
--------------------------------------------------------------------------------
/src/app/ReadOnlyProperty.kt:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | import kotlin.properties.ReadOnlyProperty
4 | import kotlin.reflect.KProperty
5 |
6 | class LogReadOnlyProperty(val data: String): ReadOnlyProperty {
7 | var counter: Int = 0
8 | override fun getValue(thisRef: Any, property: KProperty<*>): String {
9 | println("Access property ${property.name} with value $data")
10 | counter++
11 | return "$counter.${data.toUpperCase()}"
12 | }
13 | }
14 |
15 | class NameWithLog(param: String){
16 | val name: String by LogReadOnlyProperty(param)
17 | }
18 |
19 | fun main() {
20 | val nameWithLog = NameWithLog("Eko Kurniawan")
21 | println(nameWithLog.name)
22 | println(nameWithLog.name)
23 | }
--------------------------------------------------------------------------------
/src/app/ReadWriteProperty.kt:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | import kotlin.properties.ReadWriteProperty
4 | import kotlin.reflect.KProperty
5 |
6 | class StringLogReadWriteProperty(var data: String) : ReadWriteProperty{
7 | override fun getValue(thisRef: Any, property: KProperty<*>): String {
8 | println("Get property ${property.name} with value $data")
9 | return data
10 | }
11 |
12 | override fun setValue(thisRef: Any, property: KProperty<*>, value: String) {
13 | println("Set property ${property.name} from $data to $value")
14 | data = value
15 | }
16 | }
17 |
18 | class Person(param: String){
19 | var name: String by StringLogReadWriteProperty(param)
20 | }
21 |
22 | fun main() {
23 | val person = Person("Eko")
24 |
25 | println(person.name)
26 |
27 | person.name = "Kurniawan"
28 |
29 | println(person.name)
30 | }
--------------------------------------------------------------------------------
/src/app/StarProjection.kt:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | fun displayLength(array: Array<*>) {
4 | println("Total array is ${array.size}")
5 | }
6 |
7 | fun main() {
8 | val arrayInt: Array = arrayOf(1, 2, 3, 4, 5)
9 | val arrayString: Array = arrayOf("Eko", "Kurniawan", "Khannedy")
10 |
11 | displayLength(arrayInt)
12 | displayLength(arrayString)
13 | }
--------------------------------------------------------------------------------
/src/app/TypeErasure.kt:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | class TypeErasure(param: T){
4 | private val data: T = param
5 | fun getData(): T = data
6 | }
7 |
8 | fun main() {
9 | val data1 = TypeErasure("Eko")
10 | val dataString: String = data1.getData()
11 | println(dataString)
12 |
13 | val data2: TypeErasure = data1 as TypeErasure
14 | val dataInt = data2.getData() // error konversi
15 | println(dataInt)
16 | }
--------------------------------------------------------------------------------
/src/app/TypeProjection.kt:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | class Container(var data: T)
4 |
5 | fun copyContainer(from: Container, to: Container) {
6 | to.data = from.data
7 | }
8 |
9 | fun main() {
10 | val container1 = Container("Eko")
11 | val container2: Container = Container("Kurniawna")
12 |
13 | copyContainer(container1, container2)
14 |
15 | println(container1.data)
16 | println(container2.data)
17 | }
--------------------------------------------------------------------------------
/src/data/Fruit.kt:
--------------------------------------------------------------------------------
1 | package data
2 |
3 | class Fruit(val name: String, val quantity: Int) : Comparable {
4 |
5 | override fun compareTo(other: Fruit): Int {
6 | return quantity.compareTo(other.quantity)
7 | }
8 | }
--------------------------------------------------------------------------------
/src/data/Function.kt:
--------------------------------------------------------------------------------
1 | package data
2 |
3 | class Function(val name: String) {
4 |
5 | fun sayHello(param: T){
6 | println("Hello $param, my name is $name")
7 | }
8 |
9 | }
--------------------------------------------------------------------------------
/src/data/MyData.kt:
--------------------------------------------------------------------------------
1 | package data
2 |
3 | class MyData(val firstData: T, val secondData: U) {
4 |
5 | fun getData(): T = firstData
6 |
7 | fun getSecond(): U = secondData
8 |
9 | fun printlnData(){
10 | println("Data is $firstData $secondData")
11 | }
12 |
13 | }
--------------------------------------------------------------------------------