관계가 있는 여러 데이터를 묶어서 표현하기 위한 것. 묶으면 재사용성이 증가한다.
Object = Data + Method
Object는 structure 또는 class 로 구성할 수 있다.
structure | class |
---|---|
Value Type | Reference Type |
(복사되어 할당) | (참조되어 할당) |
Copy | Share |
Stack | Heap |
struct Location {
let x:Int
let y:Int
}
let store1=(loc:Location(x:3, y:4), name:"gs")
let store2=(loc:Location(x:10, y:15), name:"seveneleven")
print(store1.loc, store1.name)
// Store 구조체도 만들자.
struct Store{
let loc:Location
let name:String
}
let store3 = Store(loc: Location(x:12, y:13), name: "cu")
print(store3.loc, store3.name) // 위와 같은 형식의 값이 출력됨.
struct store{
let loc:Location
let name:String
let deliveryRange=2.0
func isDeliverable(userLoc:Location) -> Bool {
let distanceToStore = distance(current:userLoc, target:loc)
return distanceToStore < deliveryRange
}
}
func distance(current:(x:Int, y:Int), target:(x:Int, y:Int)) -> Double {
let distX = Double(target.x - current.x)
let distY = Double(target.y - current.y)
let dist = sqrt(distX*distX+distY*distY)
return dist
}
...
지켜야 할 약속
서비스 사용 시, 정해진 일들을 해야 함.
struct의 data
var description:String { return "Title:\(name)" }
struct Person{
var firstName:String // stored property
var lastName:String
var fullName:String{
return "\(firstName)\(lastName)" //computed property
}
}
var person1 = Person(firstName:"Jason", secondName:"Lee")
person.firstName
person.lastName
person.firstName = "Jim"
person.lastName = "Kim"
person.fullName
struct Person {
var firstName:String // stored property
var lastName:String
var fullName:String{
get {
return "\(firstName)\(lastName)"
}
set {
if let firstName = newValue.components(separatedBy:" ").first {
self.firstName = firstName
}
if let lastName = newValue.components(separatedBy:" ").last {
self.lastName = lastName
}
}
}
}
var person = Person(firstName: "lee", lastName: "yoonjong") // 원래는 안되나 setter 설정 시 가능.
person.fullName = "Jay Park"
print(person.fullName)
생성된 instance와 상관없이, struct의 type 자체의 속성을 정하고 싶을 때.
struct Person{
...
static let isAlien:Bool = false
}
print(Person.isAlien) // Instance가 아니라 Type 자체에 있는 property.
struct Person{
var firstName:String{
willSet{ // 세팅 직전
print("willSet : \(firstName) -> \(newValue)")
}
didSet { // 세팅 직후
print("didSet : \(oldValue)-> \(firstname)")
}
}
}
해당 프로퍼티가 접근될 때 그제서야 코드 실행
Why? 최적화 위해. 지금 굳이 필요없다면 미루자.
// struct 안에
lazy var isPopular:Bool = {
if fullName=="Jay Park" { return true }
else { return false }
}()
property는 호출 시 (저장된) 값을 하나 반환
method는 호출 시 어떤 작업을 한다.
판단 흐름
Instance에 귀속되나 function과 같이 기능을 수행한다.
struct Lecture {
var title:String
var maxStudent:Int = 10
var numberOfRegistered:Int = 8
// Type Property
static func 소속학원이름() -> String {
return "패캠"
}
static let target:String="Anybody"
}
var lec = Lecture(title:"iOS Basic")
print(Lecture.소속학원이름())
func remainSeats(of lec:Lecture) -> Int {
let remainSeats = lec.maxStudent - lec.numberOfRegistered
return remainSeats
}
print(remainSeats(of: lec))
위의 remainSeats를 struct Lecture에 합쳐보자.
여기에
mutating
struct의 property를 변형시킬 때 사용한다.
개념을 사용하자.
struct Lecture {
var title:String
var maxStudent:Int = 10
var numberOfRegistered:Int = 8
// Type Property
static func 소속학원이름() -> String {
return "패캠"
}
static let target:String="Anybody"
func remainSeats()-> Int{
let remainSeats = maxStudent - numberOfRegistered
return remainSeats
}
mutating func register(){ // mutating
numberOfRegistered += 1
}
}
var lec = Lecture(title:"iOS Basic")
print(lec.remainSeats())
lec.register()
print(lec.remainSeats())
왜 굳이 쓸까?
-> 위의 struct 찾는 것도 일이고, 충돌 위험도 있음.
struct Math {
static func abs(value:Int) ->Int {
if value>0 {
return value
}
else {
return -value
}
}
}
print(Math.abs(value: -20))
extension Math {
static func square(value:Int) -> Int {
return value*value
}
static func half(value:Int) -> Int {
return value/2
}
}
print(Math.square(value: 11))
또는 기존 라이브러리에 사용할 수도.
var value:Int = 3
extension Int {
func square() -> Int { return self*self}
func half() -> Int { return self/2}
}
print(value.square()) // 9 출력