Lesson 3: Classes and objects
💡 Teach Android Development
구글에서 제공하는 교육자료를 정리하기 위한 포스트입니다.
Classes
- 클래스는 객체의 청사진 입니다.
- 클래스는 객체
instances
에서 작동하는methods
가 정의되어 있습니다.
Define and use a class
클래스를 정의하고 객체의 새로운 instance
를 생성합니다.
class House {
val color: String = "white"
val numberOfWindows: Int = 2
val isForSale: Boolean = false
fun updateColor(newColor: String){...}
...
}
val myHouse = House()
println(myHouse)
Constructors
생성자가 클래스 해더에 정의될 경우 파라미터를 포함할 수 있습니다.
- 파라미터 없음
class A - 파라미터 존재
- var, val 선언이 없으면 생성자 범위 안에서만 사용 가능합니다.
class B(x: Int)
- var, val 선언이 있으면 클래스의 모든instances
에서 접근 가능합니다.
Constructor examples
class A
val aa = A()
class B(x: Int)
val bb = B(12)
println(bb.x) // compiler error unresolved reference
class C(val y: Int)
val cc = C(42)
println(cc.y) // 42
Default parameters
클래스 instances
는 기본값을 가질 수 있습니다.
- 기본값을 사용하여 필요한 생성자 수를 줄입니다.
- 기본, 필수 매개변수를 혼용할 수 있습니다.
- 여러 생성자가 필요하지 않아 더 간결합니다.
class Box(val length: Int, val width:Int = 20, val height:Int = 40)
val box1 = Box(100, 20, 40)
val box2 = Box(length = 100)
val box3 = Box(length = 100, width = 20, height = 40)
Primary constructor
클래스 해더안에 기본 생성자를 정의합니다.
class Circle(i: Int) {
init {
...
}
}
위의 방법과 동일한 기능을 합니다.
class Circle {
constructor(i: Int) {
...
}
}
Initializer block
- 초기화가 필요한 코드는
init
블록에서 처리할 수 있습니다. - 여러개의
init
블록도 허용됩니다. init
블록은 기본 생성자의body
가 됩니다.
Initializer block example
class Square(val side: Int) {
init {
println(side * 2)
}
}
val s = Square(10) // 20
Multiple constructors
constructor
키워드를 사용해서 secondary constructors 정의할 수 있습니다.- Secondary constructors는 this 키워드를 사용해서 기본 생성자를 호출하거나 기본 생성자를 호출하는 또 다른 Secondary constructors를 호출해야 합니다.
- Secondary constructors의
body
는 필수가 아닙니다.
Multiple constructors example
class Circle(val radius:Double) {
constructor(name:String) : this(1.0)
constructor(diameter:Int) : this(diameter / 2.0) {
println("in diameter constructor")
}
init {
println("Area: ${Math.PI * radius * radius}")
}
}
val c = Circle(3)
Properties
- val, var를 사용하여 클래스의
Properties
을 정의합니다. .
을 사용하여Properties
에 접근합니다.- var로 선언된
Properties
는.
로 접근하여 값을 설정할 수 있습니다.
Person class with name property
class Person(var name: String)
fun main() {
val person = Person("Alex")
println(person.name) Access with .<property name>
person.name = "Joey" Set with .<property name>
println(person.name)
}
Custom getters and setters
기본 get/set 사용을 원하지 않을 경우 사용 합니다.
var propertyName: DataType = initialValue
get() = ...
set(value) {
...
}
Custom getter
class Person(val firstName: String, val lastName:String) {
val fullName:String
get() {
return "$firstName $lastName"
}
}
val person = Person("John", "Doe")
println(person.fullName) // John Doe
Custom setter
var fullName:String = ""
get() = "$firstName $lastName"
set(value) {
val components = value.split(" ")
firstName = components[0]
lastName = components[1]
field = value
}
person.fullName = "Jane Smith"
Inheritance
- 단일 부모 클래스를 상속할 수 있습니다.
- 각 클래스에는 superclass라고 하는 하나의 부모 클래스가 있습니다.
- 각 하위 클래스는 superclass가 상속한 항목을 포함하고 superclass의 모든
members
를 상속합니다. - 하나의 클래스만 상속받을 수 있으므로, 원하는 만큼 implement 할 수 있는
interface
를 정의할 수 있다.
Interfaces
- 구현한 모든 클래스가 준수해야 하는 규약을 제공합니다.
- 매소드명과 속성 이름을 포함할 수 있습니다.
- 다른 인터페이스에서 파생될 수 있습니다.
Interface example
interface Shape {
fun computeArea() : Double
}
class Circle(val radius:Double) : Shape {
override fun computeArea() = Math.PI * radius * radius
}
val c = Circle(3.0)
println(c.computeArea()) // 28.274333882308138
Extending classes
- 기존 클래스를 핵심으로 사용하는 새로운 클래스를 만듭니다.(subclass)
- 새로운 클래스를 만들지 않고 클래스에 기능을 추가합니다.(extension functions)
Creating a new class
- 클래스는 기본적으로 다른 곳에서의 상속을 허용하지 않습니다.
- 상속을 허용할 경우
open
키워드를 사용합니다. Properties
,functions
은override
키워드를 통해 재정의합니다.
Classes are final by default
class A
class B : A
Error: A is final and cannot be inherited from
Use open keyword
open class C
class D : C()
Overriding
- 재정의할 수 있는
properties
와methods
에 대해open
을 사용해야 합니다.(그렇지 않을 경우 컴파일 오류 발생) properties
와methods
를 재정의 할때override
키워드를 사용해야 합니다.override
로 표시된 것은 하위 클래스에서 재정의될 수 있습니다.(기본적으로 open, 하위 클래스에서 재정의를 막고 싶으면 final 추가)
Abstract classes
- 클래스가
abstract
로 표시되야 합니다. - 인스턴스화할 수 없으며 서브클래스만 가능합니다.
- 인터페이스와 유사하지만 상태저장 기능이 추가적으로 있습니다.
abstract
로 표시된properties
와methods
는 재정의해야 합니다.abstract
로 표시되지 않은properties
와methods
를 포함할 수 있다.
Example abstract classes
abstract class Food {
abstract val kcal : Int
abstract val name : String
fun consume() = println("I'm eating ${name}")
}
class Pizza() : Food() {
override val kcal = 600
override val name = "Pizza"
}
fun main() {
Pizza().consume() // "I'm eating Pizza"
}
When to use each
- 광범위한 행동이나 유형을 정의할땐 인터페이스를 고려합니다.
- 동작이 해당 유형에만 해당될땐 클래스를 고려합니다.
- 여러 클래스에서 상속해야할 경우 리팩트링을 고려하여 일부 동작을 인터페이스로 분리할 수
있는지 확인합니다. - 일부
properties
와methods
를 하위 클래스에서 재정의되도록 하고 싶을 경우 추상화 클래스를 고려합니다. - 하나의 클래스만
extend
할 수 있지만 여러 인터페이스를implement
할 수 있습니다.
Extension functions
직접 수정할 수 없는 기존 클래스에 함수를 추가합니다.
- 구현자가 추가한 것처럼 보입니다.
- 기존 클래스를 실제로 수정하지 않습니다.
private
인스턴스 변수에 접근할 수 없습니다.
Why use extension functions?
open
되지 않은 클래스에 기능을 추가할 수 있습니다.- 소유하지 않은 클래스에 기능을 추가할 수 있습니다.
- 소유한 클래스의 헬퍼 메소드에서 핵심 API를 분리할 수 있습니다.
note: 클래스와 같은 파일이나 잘 정의된 함수와 같이 쉽게 검색할 수 있는 위치에 확장함수를 정의합니다.
Extension function example
fun Int.isOdd(): Boolean { return this % 2 == 1 }
3.isOdd() // true
Special classes
Data class
- 데이터를 저장하기 위한 클래스입니다.
- 클래스에
data
키워드로 표시합니다. - 각 속성에 대해 getter 및 setter(var일 경우)를 생성합니다.
toString()
,equals()
,hashCode()
,copy()
메서드 및 다양한 연산자를 생성합니다.
Data class example
data class Player(val name: String, val score: Int)
val firstPlayer = Player("Lauren", 10)
println(firstPlayer) // Player(name=Lauren, score=10)
Pair and Triple
- 2개나 3개의 데이터를 저장하는 사전 정의된 데이터 클래스입니다.
.first
,.second
,.third
를 사용하여 변수에 접근합니다.
Pair and Triple examples
val bookAuthor = Pair("Harry Potter", "J.K. Rowling")
println(bookAuthor) // (Harry Potter, J.K. Rowling)
val bookAuthorYear = Triple("Harry Potter", "J.K. Rowling", 1997)
println(bookAuthorYear) // (Harry Potter, J.K. Rowling, 1997)
println(bookAuthorYear.third) // 1997
Pair to
to
를 사용하면 괄호와 마침표를 생략할 수 있습니다.
val bookAuth1 = "Harry Potter".to("J. K. Rowling")
val bookAuth2 = "Harry Potter" to "J. K. Rowling"
Map
및 HashMap
과 같은 컬렉션에서도 사용됩니다.
val map = mapOf(1 to "x", 2 to "y", 3 to "zz")
Enum class
지정된 값 집합으로 사용자 정의 데이터 타입입니다.
- 인스턴스가 여러 상수 값중 하나가 되도록할 때 사용합니다.
- 상수 값은 기본적으로 사용자에게 표시되지 않습니다.
- 클래스 앞에
enum
키워드를 사용합니다.
Enum class example
enum class Color(val r: Int, val g: Int, val b: Int) {
RED(255, 0, 0), GREEN(0, 255, 0), BLUE(0, 0, 255)
}
println("" + Color.RED.r + " " + Color.RED.g + " " + Color.RED.b) // 255 0 0
Object/singleton
- 클래스의 인스턴스가 하나만 존재하길 원할 때 사용합니다.
- 클래스 키워드 대신
object
키워드를 사용합니다.
Object/singleton example
object Calculator {
fun add(n1: Int, n2: Int): Int {
return n1 + n2
}
}
println(Calculator.add(2,4)) // 6
Companion objects
- 클래스의 모든 인스턴스가 이곳에 선언된 변수나 함수를 하나의 인스턴스로 공유합니다.
companion
키워드를 사용합니다.ClassName.Property
또는ClassName.Function
을 통해 참조됩니다.
Companion object example
class PhysicsSystem {
companion object WorldConstants {
val gravity = 9.8
val unit = "metric"
fun computeForce(mass: Double, accel: Double): Double {
return mass * accel
}
}
}
println(PhysicsSystem.WorldConstants.gravity) // 9.8
println(PhysicsSystem.WorldConstants.computeForce(10.0, 10.0)) // 100.0
Organizing your code
Single file, multiple entities
- Kotlin은 파일 규칙당 단일 entitiy(class/interface)를 강제하지 않습니다.
- 같은 파일안의 연관된 구조를 그룹화할 수 있고, 해야합니다.
- 파일의 길이와 지저분함을 염두에 두어야 합니다.
Packages
- 조직을 위한 수단 제공
- 식별자는 일반적으로 소문자 단어로 마침표로 구분합니다.
package
키워드 다음에 오는 파일에서 주석이 없는 첫 번째 코드 줄에 선언됩니다.- org.example.game
Example class hierarchy
Visibility modifiers
- 가시성 수정자를 사용하여 노출 정보를 제한합니다.
- public은 외부에서 볼 수 있음을 의미합니다. 클래스의 변수나 메소드를 포함하여 모든 것이 기본적으로 공개됩니다.
- private은 오직 해당 클래스(또는 함수로 작업하는 경우 소스 파일)에서만 볼 수 있음을 의미합니다.
- protected는 private와 동일하지만, 모든 subclass에서 볼 수 있습니다.
Author And Source
이 문제에 관하여(Lesson 3: Classes and objects), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@haanbink/Lesson-3-Classes-and-objects저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)