티스토리 뷰
[시작]
- 프로퍼티 : 클래스, 구조체 또는 열거형 등에 관련된 값
- 메서드 : 특정 타입에 관련된 함수
- 프로퍼티의 종류
: 저장 프로퍼티 -> 인스턴스의 변수 또는 상수 -> 인스턴스 변수
: 연산 프로퍼티 -> 특정 연산을 실행한 결과값
: 타입 프로퍼티 -> 특정 타입에 사용되는 프로퍼티 -> 클래스 변수
- 프로퍼티 감시자
: 프로퍼티 값의 변화에 따른 특정 액션을 실행
: 저장 프로퍼티에 적용, 상속받을 수 있음
[저장 프로퍼티 (Stored Properties)]
- 클래스 또는 구조체의 인스턴스와 연관된 값을 저장하는 프로퍼티
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | struct Point{ var x: Int = 0 var y: Int = 0 } let firstPoint = Point() let secondPoint = Point(x: 10, y: 20) //구조체의 경우 프로퍼티에 맞는 생성자를 자동으로 제공해 줌 class Position{ var point: Point = Point() var name: String = "Swift" init() {} init(point: Point, name: String) { self.point = point self.name = name } } let position = Position() //클래스의 경우 옵셔널이 아니라면 프로퍼티 정의 시 초기화를 해주거나 생성자를 활용하여 프로퍼티 초기화를 해주어야 함 //매개변수가 있는 생성자를 정의해 주었다면 매개변수가 없는 생성자도 명시해 주어야 함 | cs |
[지연 저장 프로퍼티 (Lazy Stored Properties)]
- 호출이 있어야 값을 초기화, lazy 키워드 사용
- var 키워드를 사용하여 변수로 정의해야 함 -> 상수는 인스턴스가 생성되기 전에 초기화해야 함
- 복잡한 클래스나 구조체를 구현할 때 사용됨
: 클래스 인스턴스의 저장 프로퍼티로 다른 클래스 인스턴스나 구조체 인스턴스를 할당해야 할 때,
인스턴스를 초기화하면서 저장 프로퍼티로 쓰이는 인스턴스들이 한 번에 생성되어야 하는 경우,
굳이 모든 저장 프로퍼티를 사용할 필요가 없는 경우
-> 불필요한 성능 저하나 공간 낭비를 줄일 수 있음
[연산 프로퍼티 (Computed Properties)]
- 특정 상태에 따른 값을 연산하는 프로퍼티
- 접근자(getter) : 인스턴스 내외부의 값을 연산하여 적절한 값을 반환
- 설정자(setter) : 은닉화된 내부의 프로퍼티 값을 간접적으로 설정
- 클래스, 구조체, 열거형에 연산 프로퍼티 정의 가능
- 메서드 대신 연산 프로퍼티를 활용하는 경우
: 기존 Java에서 get메소드와 set메소드를 모두 명시했을 때 가독성이 떨어지는 경우가 있었음
: 이를 해결해줄 수 있으며 형식 자체가 프로퍼티 쪽이 훨씬 간편하고 직관적임
- 읽기/쓰기, 읽기 전용 구현 가능
: 쓰기 전용 구현 불가능
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | struct Point{ var x: Int = 0 var y: Int = 0 var oppositePoint: Point{ get{ return Point(x: -x, y: -y) } set(value){ x = -value.x y = -value.y } //set의 전달인자를 명시하지 않으면 자동으로 newValue라는 이름의 전달인자 생성됨 } } var point = Point() var oppositePoint = Point(x: 12, y: 42).oppositePoint //get 메서드 호출 point.oppositePoint = Point(x: 42, y: 91) //set 메서드 호출 | cs |
get 메서드는 반드시 값을 반환해야 함
[프로퍼티 감시자]
- 프로퍼티의 값이 변경됨에 따라 적절한 액션을 취하게끔 할 수 있음
- 일반 저장 프로퍼티에만 적용할 수 있음
- 프로퍼티 재정의를 통해 상속받은 저장 프로퍼티 또는 연산 프로퍼티에도 적용할 수 있음
- willSet 메서드.: 프로퍼티가 변경될 값이 전달인자로 넘어옴, newValue
- didSet 메서드 : 프로퍼티가 변경되기 전 값이 전달인자로 넘어옴, oldValue
1 2 3 4 5 6 7 8 9 10 11 12 13 | struct MyInfo{ var name: String = "Swift"{ willSet{ print("\(name) -> \(newValue)") } didSet{ print("\(oldValue) -> \(name)") } } } var myInfo: MyInfo = MyInfo() myInfo.name = "Objective - C" | cs |
- 연산 프로퍼티와 프로퍼티 감시자는 전역변수, 지역변수에도 사용 가능
: 함수나 메서드, 클로저, 클래스, 구조체, 열거형 등의 범위 안에 포함되지 않았던 변수(상수)
- 전역변수는 처음 접근할 때 최초로 연산이 이루어지므로 lazy 키워드를 사용하여 지연시킬 필요가 없음
- 지역변수는 절대 지연 연산되지 않음
[타입 프로퍼티 (Type Properties)]
- 타입 자체에 속하는 프로퍼티
: 타입 프로퍼티의 값은 하나
: 그 타입의 모든 인스턴스가 공통으로 사용하는 값 (static constant)
: 모든 인스턴스에서 공용으로 접근하고 값을 변경할 수 있는 변수 (static variable)
- 저장 타입 프로퍼티는 변수 또는 상수로 선언 가능, 반드시 초깃값을 설정, 지연 연산됨
- 연산 타입 프로퍼티는 변수로만 선언 가능
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class Class{ static var typeProperty: Int = 0 var instanceProperty: Int = 0{ didSet{ Class.typeProperty = instanceProperty + 100 } } static var typeComputedProperty: Int{ get{ return typeProperty } set{ typeProperty = newValue } } } Class.typeProperty = 123 //인스턴스를 생성하지 않고 호출 가능 let classInstance = Class() classInstance.instanceProperty = 100 Class.typeProperty //200 Class.typeComputedProperty //200 | cs |
[키 경로]
- 프로퍼티의 위치만 참조하도록 할 수 있음
- 타입 간 의존성을 낮추는 데 많은 도움을 줌
- 나중에 다시 알아보자
1 2 3 4 5 6 7 8 9 10 11 12 13 | class Person{ var name: String init(name: String) { self.name = name } } struct Stuff{ var name: String var owner: Person } let stuff = Stuff(name: "ObjC", owner: Person(name: "Swift")) print(stuff[keyPath: \Stuff.owner.name]) //Swift | cs |
[메서드]
- 특정 타입에 관련된 함수
- 클래스, 구조체, 열거형에서 메서드 정의 가능
- 타입 메서드 == 클래스 메서드
- 인스턴스 메서드 : 특정 타입 내부에 구현한 함수
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Class{ var number: Int = 0 func increase(){ number += 1 } func decrease(){ number -= 1 } } let instance = Class() instance.increase() instance.increase() instance.decrease() print(instance.number) //1 | cs |
- 구조체나 열거형은 값 타입이므로 메서드가 자신의 프로퍼티 값을 수정할 때 메서드 앞에 mutating 키워드를 명시해야 함
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | struct Class{ var number: Int = 0 mutating func increase(){ number += 1 } mutating func decrease(){ number -= 1 } } var instance = Class() instance.increase() instance.increase() instance.decrease() print(instance.number) //1 | cs |
- self 프로퍼티 : Java의 this와 비슷, 인스턴스 프로퍼티를 지칭하고 싶을 때 사용
: 구조체, 열거형은 self 프로퍼티를 사용하여 자신 자체를 치환할 수도 있음
: 클래스의 인스턴스는 참조 타입이므로 self 프로퍼티에 다른 참조를 할당할 수 없음
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class LevelClass{ var level: Int = 0 func reset(){ //self = LevelClass() //오류 } } struct LevelStruct{ var level: Int = 0 mutating func levelUp(){ level += 1 print("Level : \(level)") } mutating func reset(){ self = LevelStruct() } } var levelStruct = LevelStruct() levelStruct.levelUp() //Level : 1 levelStruct.levelUp() //Level : 2 levelStruct.reset() levelStruct.levelUp() //Level : 1 | cs |
[타입 메서드]
- 클래스 메서드와 유사
- static 키워드로 정의하면 상속 후 메서드 재정의가 불가능
- class 키워드로 정의하면 상속 후 메서드 재정의가 가능
- self 프로퍼티는 타입 메서드 내에서 타입 이름과 같은 의미로 사용됨
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class Parent{ static func staticTypeMethod(){ print("Parent staticTypeMethod") } class func classTypeMethod(){ print("Parent classTypeMethod") } static func hi(){ self.classTypeMethod() } } class Child: Parent{ /*override static func staticTypeMethod(){ print("Hi") }*/ //오류 override class func classTypeMethod(){ print("Hi") } } Parent.classTypeMethod() //Parent classTypeMethod Child.classTypeMethod() //Hi Parent.hi() //Parent classTypeMethod | cs |
'Swift > 야곰의 스위프트' 카테고리의 다른 글
12장 접근제어 (0) | 2018.02.05 |
---|---|
11장 인스턴스 생성 및 소멸 (0) | 2018.02.05 |
9장 구조체와 클래스 (0) | 2018.02.03 |
8장 옵셔널 (0) | 2018.02.03 |
7장 함수 (0) | 2018.01.29 |