반응형
- 몇가지 스위프트 언어의 특징 (공식 소개 링크)
- Modern
- 최근 개발언어에 대해 연구해서 좋은것만 넣어서 업데이트 하고 있음
- 코드를 깔끔하게 작성할수 있게 설계함
- 개발자들이 실수 덜 할수 있게 고도화를 지속적으로 하고 있음
- 메모리 관리도 자동으로 됨
- Safety
- 스위프트는 안전하지 않은 형태의 클래스를 제거함
- 문법과 시스템을 통해서, 발생할수 있는 위험성을 제거함
- Fast
- 스위프트는 최초부터 빠르게 설계되었음
- C, Objective-C 등과 호환도 되지만, 기본적으로 더 빠른 속도로 기존 언어들을 대체하려고 나옴
- Modern
func printNames(_ names: String...) {
for name in names {
print("name is \\(name)")
}
}
printNames("James", "Roy", "Jake")
// name is James
// name is Roy
// name is Jake
enum DivideError: Error {
case cannotZero
}
func divide(dividend: Int, divisor: Int) throws -> Int {
if divisor == 0 {
throw DivideError.cannotZero
}
return Int(dividend / divisor)
}
do {
let result = try divide(dividend: 80, divisor: 6)
// let result = try divide(dividend: 80, divisor: 0)
print(result)
} catch {
print(error.localizedDescription)
}
func makeTriple(num: inout Int) {
num *= 3
}
var num = 8
makeTriple(num: &num)
print(num) // 24
- 클로져도 사실 함수처럼 “어떤 태스크를 수행하기 위한 코드 블록” 임
💡 struct vs. class 차이점과 공통점
✅ 공통점
- 프로퍼티(속성)를 정의해서 값을 저장할수 있음
- 메소드(행동)를 정의해서 기능을 제공할수 있음
- 생성자를 정의해서 초기상태를 세팅할수 있음
- 확장을 이용해서, 기본 구현외 추가 기능을 더할수 있음
- 프로토콜을 구현해서 특정 기능을 제공할수 있음
✅ 차이점
- 클래스는 상속을 시킬수 있음
- 클래스는 레퍼런스 카운팅을 통해 클래스 인스턴스에 대한 하나 이상의 참조를 허용
- 클래스는 deinitializer 호출시, 이미 할당된 리소스에서 해제 할수 있음
Struct
struct Movie {
// stored property
var name: String
var director: String
// computed property
var description: String {
return "\\(name) is \\(director)'s best movie ever"
}
}
var movie = Movie(name: "인셉션", director: "놀란")
print(movie.description)
struct Task {
var name: String
var progress: Int {
didSet {
print("Current Progress : \\(progress) %")
}
}
var isDone: Bool {
return progress == 100
}
}
var task = Task(name: "Very Important Task", progress: 0)
task.progress = 30 // Current Progress : 30 %
task.progress = 50 // Current Progress : 50 %
task.progress = 90 // Current Progress : 90 %
method
- 객체는 행동(기능)을 가지고 있고, 그것을 우리는 method 라고 부름
- 객체가 가지고 있는 함수라고 생각하면 됨
- struct 에서 method 가 stored property 값을 변경하는 경우, mutating 키워드를 메소드 앞에 붙여주어야함
struct Student {
let name: String
var major: String
var knowledge: Double
func didFinalTest() -> Int {
let howMuchIdontKnow = (1 - knowledge) * 100
let score = 100 - Int(howMuchIdontKnow)
return score
}
mutating func didStudy() {
if knowledge >= 1 {
knowledge = 1
} else {
knowledge += 0.1
}
}
}
initializer (생성자)
- 해당 struct 를 만들수 있게 해주는 특별한 타입의 메소드
- init 키워드를 이용해서 생성함
- struct 는 meberwise initializer 가 기본으로 따라옴
// -------------------------------------------------//
// initializer(생성자)
struct iPhone {
var model: String
init() {
model = "iPhone 13"
}
}
let iPhone13 = iPhone()
// init() 정의 안해줬으면 에러 안났을 텐데 생성자를 정의해줘서 해당 값 에러남.
//let iPhone14 = iPhone(model: "iPhone 14")
// -------------------------------------------------//
// 현재 객체 지칭 - self
struct iPhone2 {
var model: String
init(model: String = "iPhone 13") {
self.model = model
}
}
let iPhone2_13 = iPhone2()
let iPhone2_14 = iPhone2(model: "iPhone 14")
// -------------------------------------------------//
// Lazy properties
struct Transactions {
init() {
print("Loading self history.. ")
}
}
struct SecondHandItem {
var name: String
// var history: Transactions = Transactions()
lazy var history: Transactions = Transactions()
init(name: String) {
self.name = name
}
}
Access Control
- 접근 제어 - internal defau
- 외부 접근 가능 > public > internal > fileprivate > private > 내부 접근 가능
// -------------------------------------------------//
// Access Control
//- 외부 접근 가능 > `public` > `internal` (default) > `fileprivate` > `private` > 내부 접근 가능
struct UserAccount {
private var id: String
private var bill: Int
var name: String
init(id: String, bill: Int, name: String) {
self.id = id
self.bill = bill
self.name = name
}
func billDescription() -> String {
return "\\(id)'s billing amount : \\(bill) name : \\(name)"
}
}
var user01 = UserAccount(id: "1234", bill: 400, name: "Mike")
//user01.bill = 100 - 에러남 접근 안됨.
//user01.id = "1123" - 에러남 접근 안됨.
user01.name = "joy" // 접근 가능.
let billDescription01 = user01.billDescription()
Class
- class 는 struct 와 다르게 memberwise initializer 제공되지 않음
class Dog {
var name: String
var breed: String
init(name: String, breed: String) { // 안해주면 에러남!!!
self.name = name
self.breed = breed
}
}
- class 와 struct 차이중 하나는 class 는 상속을 제공함
class Collie: Dog {
init(name: String) { // 이거 안해주면 부모클래스 생성자 따라감.
super.init(name: name, breed: "Collie")
}
}
let milky = Collie(name: "milky")
milky.name // milkiy
milky.breed // Collie
copying object
- struct 와 class 의 차이중 하나가 instance 복사할때임
- struct 와 같은 value type 은 복사하면, 새로운 객체를 만듬
- → 따라서, 새로 복사된 객체의 프로퍼티 변형했다고 원래 객체가 영향 받지 않음
- class 와 같은 reference type 은 복사하면, 새로운 객체를 만들지 않음 (같은 객체를 포인팅하고 있음)
- → 따라서, 새로 복사된 객체의 프로퍼티 변형하면, 원래 객체의 프로퍼티 영향 받아서 변형 되어 있음
- struct 와 같은 value type 은 복사하면, 새로운 객체를 만듬
class StudentClass {
var name: String
init(name: String) {
self.name = name
}
}
struct StudentStruct {
var name: String
}
var studentClass1 = StudentClass(name: "Jacob")
var studentClass2 = studentClass1
studentClass2.name = "Jay"
studentClass1.name // Jay
studentClass2.name // Jay
var studentStruct1 = StudentStruct(name: "Jacob")
var studentStruct2 = studentStruct1
studentStruct2.name = "Jay"
studentStruct1.name // Jacob
studentStruct2.name // Jay
deinitializer
- struct 와 class 의 차이중 하나가 class 는 deinitializer 가 있음
- 해당 인스턴스가 메모리에서 해제될때(없어질때) 호출됨
class Human {
var name: String
init(name: String) {
self.name = name
print("initialize instance")
}
deinit {
print("deintilize instance: \\(name)")
}
func printName() {
print("my name: \\(self.name)")
}
}
func createJohn() {
let john = Human(name: "John")
john.printName()
}
createJohn() // 함수가 끝나면 함수내에 변수가 메모리 해제되어 deintilize 호출됨.
// initialize instance
// my name: John
// deintilize instance: John
let john = Human(name: "John")
john.printName()
// initialize instance
// my name: John
mutability
- class 는 struct 와 다르게 reference type 이여서 상수로 선언하더라도, 프로퍼티가 var 로 선언해 놓았으면 변경 가능함
- 이 때문에, class 는 method 앞에 mutating 키워드를 쓸 필요 없음
- 프로퍼티를 변경가능하지 않게 하려면, let 으로 선언해 놓으면 됨
class Human {
var name: String
init(name: String) {
self.name = name
print("initialize instance")
}
deinit {
print("deintilize instance: \\(name)")
}
func printName() {
print("my name: \\(self.name)")
}
func updateName(to name: String) {
self.name = name
}
}
let sean = Human(name: "Sean")
sean.name // Sean
sean.name = "Joy" // sean이 let 이지만 name 이 var 이기 때문에 변경 가능.
sean.name // Joy
sean.updateName(to: "Son")
sean.name // Son
https://developer.apple.com/documentation/swift/choosing-between-structures-and-classes
Struct vs Class
- Use structures by default. :
- 기본적으로 잘 모르겠으면 struct를 쓴다.
- Use classes when you need Objective-C interoperability.
- Objective-C 상호 운용성이 필요할 때 class 를 쓴다.
- Use classes when you need to control the identity of the data you’re modeling.
- 모델링 중인 데이터의 identity를 제어해야 하는 경우 class 를 쓴다.
- Use structures along with protocols to adopt behavior by sharing implementations.
- 프로토콜을 채택할 때 struct를 쓴다.
Protocol
- protocol 은 어떤 약속(역할)을 정해 놓은 것 어떤 약속(역할)을 정해 놓은 것이지 아직 구현된것은 아님
한가지 객체에 대해서만 buy() 메소드를 정의할 때
struct Book {
var name: String
}
func buy(_ book: Book) {
print("I'm buying \\(book.name)")
}
let harrypotter = Book(name: "Harry Potter")
buy(harrypotter)
**Purchaseable** 역할에 buy() 메소드를 정의할때
protocol Purchaseable {
var name: String { get set }
}
func buy(_ item: Purchaseable) {
print("I'm buying \\(item.name)")
}
struct Book: Purchaseable {
var name: String
var author: String
}
struct Movie: Purchaseable {
var name: String
var actors: [String]
}
struct Car: Purchaseable {
var name: String
var manufacturer: String
}
struct Coffee: Purchaseable {
var name: String
var strength: Int
}
let harryPotter = Book(name: "HarryPotter", author: "J.K. Rowling")
let topgun = Movie(name: "Top Gun", actors: ["Tom cruise"])
let modelX = Car(name: "modelX", manufacturer: "Tesla")
let americano = Coffee(name: "ahah", strength: 5)
buy(harryPotter)
buy(topgun)
buy(modelX)
buy(americano)
Protocol 상속
- protocol 은 상속 받을수 있음
- 클래스와 다르게 여러개 상속이 가능함
- 여러개 상속이 되다 보니, protocol 을 더 작고 명확하게 나눌수 있음
- 재사용성도 늘고 테스트 가능성도 더 높아짐
protocol Payable {
func calculateWages() -> Int
}
protocol Trainable {
func train()
}
protocol HasVacation {
func takeVacation(days: Int)
}
protocol Employee: Payable, Trainable, HasVacation { }
struct DeveloperEmployee: Employee {
var name: String
func calculateWages() -> Int {
return 10_000_000
}
func train() {
print("study hard")
}
func takeVacation(days: Int) {
print("take \\(days) days off")
}
}
let choi = DeveloperEmployee(name: "Choi")
choi.calculateWages()
choi.takeVacation(days: 3)
choi.train()
Protocol Extension
- protocol 은 어떤 역할에 대한 정의를 설명해줌
- 다만, 실제 구현은 제공하지 않음
- extension 은 기능에 대한 구현까지 제공함
- 다만, 한가지 타입에만 적용됨
- protocol extension 은 위에 있는 두가지 단점을 보완해 줄수 있음
- protocol 에 기본 구현을 제공해줄수 있음
- protocol 을 채택하는 여러 타입에 기능을 제공해줄수 있음
extension Collection {
func summarize() {
print("There are \\(count) members")
}
}
let stringArray = ["aa", "bb", "cc"]
let numSet = Set([1, 2, 3, 4, 5])
stringArray.summarize()
// There are 3 members
numSet.summarize()
// There are 5 members
Protocol Oriented Programming
- protocol 은 어떤 역할에 대한 정의를 제공
- extension 은 어떤 타입에 구현을 제공함
- protocol extension 은 어떤 역할에 대한 기본 구현 제공
- 위 3가지 덕분에 POP(protocol oriented programming)이 가능함
protocol Payable {
func calculateWages() -> Int
}
protocol Trainable {
func train()
}
protocol HasVacation {
func takeVacation(days: Int)
}
extension Payable {
func calculateWages() -> Int {
return 10_000_000
}
}
extension Trainable {
func train() {
print("study hard")
}
}
extension HasVacation {
func takeVacation(days: Int) {
print("take \\(days) days off")
}
}
protocol Employee: Payable, Trainable, HasVacation { }
struct DeveloperEmployee: Employee {
var name: String
}
let choi = DeveloperEmployee(name: "Jason")
choi.calculateWages()
choi.takeVacation(days: 3)
choi.train()
struct DesignerEmployee: Employee {
var name: String
}
let jane = DesignerEmployee(name: "jane")
jane.calculateWages()
jane.takeVacation(days: 5)
jane.train()
Typecasting
- swift 에서는 부모 타입에서 자식 타입으로 변형가능한지 확인해볼때 as? 키워드를 사용함
https://github.com/jiyeonjoy/SwiftStudy
반응형
'# 02 > Swift' 카테고리의 다른 글
[Swift] RxSwift (0) | 2023.01.11 |
---|---|
[Swift] DispatchQueue / Serial / Concurrent (0) | 2023.01.11 |
[Swift] DFS/BFS (0) | 2022.12.18 |
[Swift] MaxHeap (0) | 2022.12.12 |
[Swift] MinHeap (0) | 2022.12.12 |