본문 바로가기

그냥 개인공부

Swift 기본문법 4

드디어 기본 문법 마무리 하는 날! 두구두구두구🥁

더이상 세미콜론으로 싸우지 말자🤭

 

"세미콜론도 입력할 필요가 없습니다."


타입캐스팅: 인스턴스의 타입을 확인하거나 어떠한 클래스의 인스턴스를 해당 클래스 계층 구조의 슈퍼 클래스나 서브 클래스로 취급하는 방법

  • 타입 캐스팅 연산자  is, as
class MediaItem {
   var name: String
   init (name: String) {
      self.name = name
   }
}

// MediaItem class 상속
class Movie: MediaItem {
   var director: String
   init(name: String, director: String) {
      self.director = director
      super.init(name: name)
   }
}

// MediaItem class 상속
class Song: MediaItem {
   var artist: String
   init(name: String, artist: String) {
   super.init(name: name)
   }
}

let library = [
   Movie(name: "Parasite" , director: "봉준호"),
   Song(name: "Butter", director: "BTS"),
   Movie(name: "Old Boy", director: "박찬욱" ),
   Song(name: Wonderwall, director: "Oasis"),
   Song(name: "Rain", director: "이적" ),
]

var movieCount = 0
var songCount = 0

for item in library {
   if item is Movie {
      movieCount += 1
   } else if item is Song {
      songCount += 1
   }
}

print("Media library contains \(movieCount) movies and \(songCount) songs") // Media library contains 2 movies and 3 songs

// 다운 캐스팅
for item in library {
   if let movie = item as? Movie {
      print("Movie: \(movie.name), dir. \(movie.director)")
   } else if let song = item as? Song {
      print("Song: \(song.name), by \(song.artist)")
   }
}
*/
Movie: Parasite, dir. 봉준호
Song: Butter, by BTS
Movie: Old Boy, dir. 박찬욱
Song: Wonderwall, by Oasis
SOng: Rain, by 이적
/*

 

assert와 guard

1. assert

  • 특정 조건을 체크하고, 조건이 충족되지 않으면 메세지를 출력하게 하는 함수
  • 디버깅 모드에서만 동작하고 주로 디버깅 중 조건의 검증을 위해 사용

2. guard

  • 뭔가를 검사해 그 다음에 오는 코드를 실행할지 말지 결정함
  • 설정한 조건문이 거짓일 때 구문이 실행됨
// assert
var value = 0
assert(value == 0)

value = 2
assert(value == 0, "Value is not zero") // throw error


// guard
guard 조건 else {
   조건이 false면 else 구문이 실행되고
   return or throw or break를 통해 이후 코드를 실행하지 않도록 한다.
}

func guardTest(value: Int) {
   guard value == 0 else { return }
   print("Hello")
}

guardTest(value: 2) // nothing happens
guardTest(value: 20) // Hello

어떻게 활용할 지 아직 감이 오지 않는다.. 필요할 때 다시 복습하기로

 

프로토콜: 특정 역할을 하기 위한 메서드, 프로퍼티, 기타 요구사항 등의 청사진

protocol 이름 {
}

protocol SomeProtocol {
}

protocol SomeProtocol2 {
}

// 프로토콜 채택
struct SomeStructure: SomeProtocol {
}

// 복수의 프로토콜 동시에 채택
struct SomeStructure2: SomeProtocol, SomeProtocol2 {
}

// class에 프로토콜을 채택
// 상속받을 superclass를 제일 먼저 써준다
class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
}

// 프로토콜 채택시 요구사항 추가
protocol FirstProtocol {
   // 상수(let)가 아니라 변수(var)로 요구해야 한다.
   var name: Int { get set } // 읽기, 쓰기 둘다 가능
   var age: Int { get } // 읽기만 가능
}

// 타입 프로퍼티 요구하려면 static 써야함
protocol AnotherProtocol {
   static var someTypeProperty: Int { get set }
}

protocol FullyNamed {
   var fullName: String { get set }
   func printFullName()
}

struct Person: FullyNamed {
   var fullName: String // 프로토콜 준수
   func printFullName() {
      print(fullName) // 구현하고자 하는 메서드 정의
   }
}

// 프로토콜 채택시 생성자 요구사항 추가
protocol SomeProtocol4 {
   init()
}

class SomeClass: SomeProtocol4 {
   required init() { // required 식별자 써야함
   }                 // 구조체에서는 required 필요없으나, class에서는 필요함
                     // 단 이 class가 상속받을 수 없는 final class라면 안써도 됨
}
protocol SomeProtocol3 {
   func someTypeMethod() // 매개변수는 정의
}

 

익스텐션: Swift의 강력한 기능 중 하나, 기존의 클래스, 구조체, 열거형, 프로토콜에 새로운 기능을 추가할 수 있음

// 기본 사용법
extension SomeType {
   // 추가할 기능들
}

// 타입에 연산 프로퍼티 추가 (저장 프로퍼티는 추가 불가)
extension Int {
   var isEven: Bool { // 짝수인지 판단
      return self % 2 == 0
   }
   
   var isOdd: Bool { // 홀수인지 판단
      return self % 2 == 1
   }
}

var number = 3
print(number.isEven) // false
print(number.isOdd) // true

// 타입에 메서드 추가
extension String {
   func convertToInt() -> Int? { // Int 타입으로 변경하는 메서드
      return Int(self)
   }
}

var string = "0"
string.converToInt() // 0

단, 기존의 기능에 override는 불가능

 

열거형: 연관성이 있는 값들을 모아 놓은 것

enum CompassPoint {
   case north
   case south
   case east
   case west
   
   // 또는 
   
   case north, south, east, west // 도 가능
}

var dicrection = CompassPoint.east // 열거형 변수
print(direction) // east
direction = .west // 컴파일러가 이미 열거형 타입이라는 것을 추론해 내부이름 항목만으로도 사용가능
print(direction) // west

// 열거형은 switch 구문과 찰떡!

switch direction {
case .north:
   print("north")
case .south:
   print("south")
case .east:
   print("east")
case .west:
   print("west")
}
// west

// 원시값 (raw value) 설정 하는 법
enum CompassPoint: String {
   case north = "북"
   case south = "남"
   case east = "동"
   case west = "서"
}

 

옵셔널 체이닝: 옵셔널에 속해 있는 nil 일지도 모르는 프로퍼티, 메서드, 서브스크립션 등을 가져오거나 호출할 때 사용하는 일련의 과정

struct Developer {
   let name: String
}

struct Company {
   let name: String
   var developer: Developer?
}

var developer = Developer(name: "Sophie")
var company = Company(name: "Gil", developer: developer)
print(company.developer?.name) // Optional(name: "Sophie")
print(company.developer!.name) // Sophie

오늘 아주 쬐끔 지루해질 뻔했지만 정적언어 문법은 생각보다 많이 흥미로웠고, 변수들을 구속하는 맛(?)이 아주 쏠쏠했다.

앞으로 기본적인 앱들을 구현해 내보면서 약 3.5일 동안 가볍게 익힌 Swift에 익숙해지도록 노력해볼 예정이다.

그리고 아직 100% 이해하지 못했거나 놓쳤거나 어떻게 쓰이는지 제대로 감이 안오는 것들은 추후에 실제로 써보면서 다시 한번 복습해야겠다.

'그냥 개인공부' 카테고리의 다른 글

Swift 기본문법 3  (2) 2022.01.07
Swift 기본문법 2  (4) 2022.01.06
Swift 기본문법 1  (5) 2022.01.05