Structure | Class |
---|---|
value | reference |
Copy | Share |
Stack(빠름) | Heap(느림) |
struct PersonStruct{
var firstName:String
var lastName:String
var fullName:String{
return "\(firstName) \(lastName)"
}
mutating func uppercaseName(){
firstName = firstName.uppercased()
lastName = lastName.uppercased()
}
}
// init은 클래스 객체 생성시 사용. 없으면 안 됨.
// struct도 init 사용 가능 (init 굳이 안써도 memberwise initializer를 제공)
class PersonClass{
var firstName:String
var lastName:String
init(firstName:String, lastName:String){
self.firstName = firstName
self.lastName = lastName
}
var fullName:String{
return "\(firstName) \(lastName)"
}
func uppercaseName(){ // mutating X
firstName = firstName.uppercased()
lastName = lastName.uppercased()
}
}
var personStruct1 = PersonStruct(firstName:"Jason", lastName:"Lee")
var personStruct2 = personStruct1
var personClass1 = PersonClass(firstName:"Jason", lastName:"Lee")
var personClass2 = personClass1
personStruct2.firstName = "Jay"
print(personStruct1.firstName) // Jason 출력 (안 바뀜! - 깊은 복사)
print(personStruct2.firstName) // Jay 출력
personClass2.firstName = "Jay"
print(personClass1.firstName) // Jay 출력 ! (바뀜! - 얕은 복사)
print(personClass2.firstName) // Jay 출력
personClass2 = PersonClass(firstName:"Bob", lastName:"Lee")
print(personClass1.firstName)
print(personClass2.firstName) // 같은 곳을 바라보고 있었는데 다른 곳을 가리키게 됨.
personClass1 = personClass2 // 1도 2를 가리키게 됨
let point1 = Point(x:3, y:5)
let point2 = Point(x:3, y:5)
→ 데이터 자체로 비교해야 하는 경우
var myMac = Mac(owner:"Jason")
var yourMac = myMac
yourMac.owner = "Jay"
print(myMac.owner)
print(yourMac.owner)
→ 요약 : 일단 Struct로 하자.
중복되는 것을 적용할 Class에
class Student:Person{
var grades:[Grade]=[]
}
let jay=Person(firstName:"Jay", lastName:"Lee")
let jason=Student(firstName:"Jason", lastName:"Kim") // initalizer 없어도 됨!
print(jay.firstName)
print(jason.firstName)
let math = Grade(letter:"B", points:0.5, credits:3)
jason.grades.append(math)
let history = Grade(letter:"A", points:10, credits:3)
jason.grades.append(history)
print(jason.grades.count)
A is B (A는 B에 포함된다.)
Student is Person.
Person : superclass(parent class)
Student : subclass(child class)
학생인데 운동선수
class StudentAthelete:Student{
var minimumTrainingTime:Int = 2
var trainingTime:Int = 0
func train(){
trainedTime += 1
}
}
A subclass can provide its own custom implementation of an instance method, type method, instance property, type property, or subscript that it would otherwise inherit from a superclass. This is known as overriding. - Swift 공식문서
운동선수인데 축구선수
class FootballPlayer:StudentAthelete{
var footballTeam = "FC swift"
override func train(){
trainingTime += 2
}
}
var athelete1 = StudentAthelete(firstName:"Sena", lastName:"Kim")
var athelete2 = FootballPlayer(firstName:"Henry", lastName:"Son")
print(athelete1.firstName)
print(athelete2.firstName)
athelete1.grades.append(math)
athelete2.grades.append(math)
athelete1.minimumTrainingTime
athelete2.minimumTrainingTime
athelete1.footballTeam // ERROR
athelete2.footballTeam
athelete1.train()
athelete2.train()
athelete1.trainingTime
athelete2.trainingTime
athelete1 = athelete2 as StudentAthelete // 가능. Uppercasing
// child class의 동일 함수를 그대로 사용하는 듯. 변수도 덮어씌워짐
athelete1.train()
athelete1.trainedTime
athelete1.footballTeam // ERROR
if let son = athelete1 as? FootballPlayer { // Downcasting
print("->team:\(son.footballTeam)")
// StudentAthelete 형태인데, FootballPlayer로 다운캐스팅하여 FootballPlayer property에 접근
순서 중요!
class StudentAthelete:Student{
var minimumTrainingTime:Int = 2
var trainingTime:Int = 0
var sports:[String]
init(firstName:String, lastName:String, sports:[String]){
// 순서가 중요하다 !
// 1st. 자식 클래스의 stored property 먼저
self.sports = sports
// 2nd. 부모 클래스의 stored property. 여기에선 Person의 init이다.
super.init(firstName:firstName, lastName:lastName)
}
}
let student1 = Student(firstName:"Jason", lastName:"Lee")
let student2 = StudentAthelete(firstName:"Jay", lastName:"Kim", sports:["football"])
Phase 1 : Person <- Student <- StudentAthelete (self.sports -> super.init)
Phase 2 : Person -> Student -> StudentAthelete (self.train)
Phase 2
- Working back down from the top of the chain, each designated initializer in the chain has the option to customize the instance further. Initializers are now able to access self and can modify its properties, call its instance methods, and so on.
- Finally, any convenience initializers in the chain have the option to customize the instance and to work with self. - 공식문서
부 initializer
convenience init(name:String){ //이름만 받겠다 !
self.init(firstName:name, lastName:"", sports:[])
}
let student3 = StudentAthelete(name:"Mike")
축소시키기
class Student:Person{
var grade:[Grade]=[]
// 주 init (=designated init)
override init(firstName:String, lastName:String){
super.init(firstName:firstName, lastName:lastName)
}
// 부 init (=convenience init)
convenience init(student:Student){
self.init(firstName:student.firstName, lastName:student.lastName)