'Type'에 해당되는 글 3건

  1. 2017.07.10 타입캐스팅 (2)
  2. 2017.06.19 클래스, 구조체, 열거형 비교
  3. 2017.02.06 Swift - 함수, 콜렉션 타입

타입캐스팅

스위프트의 타입캐스팅은 인스턴스의 타입을 확인하는 용도 또는 클래스의 인스턴스를 부모 혹은 자식 클래스의 타입으로 사용할 수 있는지 확인하는 용도로 사용합니다. is, as를 사용합니다.


소스코드


타입 캐스팅 예제를 위한 클래스 정의

class Person {
    var name: String = ""
    func breath() {
        print("숨을 쉽니다")
    }
}

class Student: Person {
    var school: String = ""
    func goToSchool() {
        print("등교를 합니다")
    }
}

class UniversityStudent: Student {
    var major: String = ""
    func goToMT() {
        print("멤버쉽 트레이닝을 갑니다 신남!")
    }
}


예제를 위한 인스턴스 생성

var yagom: Person = Person()
var hana: Student = Student()
var jason: UniversityStudent = UniversityStudent()


타입 확인

is를 사용하여 타입을 확인합니다.

var result: Bool

result = yagom is Person // true
result = yagom is Student // false
result = yagom is UniversityStudent // false

result = hana is Person // true
result = hana is Student // true
result = hana is UniversityStudent // false

result = jason is Person // true
result = jason is Student // true
result = jason is UniversityStudent // true

if yagom is UniversityStudent {
    print("yagom은 대학생입니다")
} else if yagom is Student {
    print("yagom은 학생입니다")
} else if yagom is Person {
    print("yagom은 사람입니다")
} // yagom은 사람입니다

switch jason {
case is Person:
    print("jason은 사람입니다")
case is Student:
    print("jason은 학생입니다")
case is UniversityStudent:
    print("jason은 대학생입니다")
default:
    print("jason은 사람도, 학생도, 대학생도 아닙니다")
} // jason은 사람입니다

switch jason {
case is UniversityStudent:
    print("jason은 대학생입니다")
case is Student:
    print("jason은 학생입니다")
case is Person:
    print("jason은 사람입니다")
default:
    print("jason은 사람도, 학생도, 대학생도 아닙니다")
} // jason은 대학생입니다


업 캐스팅

as를 사용하여 부모클래스의 인스턴스로 사용할 수 있도록 컴파일러에게 타입정보를 전환해줍니다. Any 혹은 AnyObject로도 타입정보를 변환할 수 있습니다. 암시적으로 처리되므로 꼭 필요한 경우가 아니라면 생략해도 무방합니다.

// UniversityStudent 인스턴스를 생성하여 Person 행세를 할 수 있도록 업 캐스팅
var mike: Person = UniversityStudent() as Person

var jenny: Student = Student()
//var jina: UniversityStudent = Person() as UniversityStudent // 컴파일 오류

// UniversityStudent 인스턴스를 생성하여 Any 행세를 할 수 있도록 업 캐스팅
var jina: Any = Person() // as Any 생략가능


다운 캐스팅

as? 또는 as!를 사용하여 자식 클래스의 인스턴스로 사용할 수 있도록 컴파일러에게 인스턴스의 타입정보를 전환해줍니다.


조건부 다운 캐스팅

as?를 사용합니다. 캐스팅에 실패하면, 즉 캐스팅하려는 타입에 부합하지 않는 인스턴스라면 nil을 반환하기 때문에 결과의 타입은 옵셔널 타입입니다.

var optionalCasted: Student?

optionalCasted = mike as? UniversityStudent
optionalCasted = jenny as? UniversityStudent // nil
optionalCasted = jina as? UniversityStudent // nil
optionalCasted = jina as? Student // nil


강제 다운 캐스팅

as!를 사용합니다. 캐스팅에 실패하면, 즉 캐스팅하려는 타입에 부합하지 않는 인스턴스라면 런타임 오류가 발생합니다. 캐스팅에 성공하면 옵셔널이 아닌 일반 타입을 반환합니다.

var forcedCasted: Student

optionalCasted = mike as! UniversityStudent
//optionalCasted = jenny as! UniversityStudent // 런타임 오류
//optionalCasted = jina as! UniversityStudent // 런타임 오류
//optionalCasted = jina as! Student // 런타임 오류


활용

func doSomethingWithSwitch(someone: Person) {
    switch someone {
    case is UniversityStudent:
        (someone as! UniversityStudent).goToMT()
    case is Student:
        (someone as! Student).goToSchool()
    case is Person:
        (someone as! Person).breath()
    }
}

doSomethingWithSwitch(someone: mike as Person) // 멤버쉽 트레이닝을 갑니다 신남!
doSomethingWithSwitch(someone: mike) // 멤버쉽 트레이닝을 갑니다 신남!
doSomethingWithSwitch(someone: jenny) // 등교를 합니다
doSomethingWithSwitch(someone: yagom) // 숨을 쉽니다


func doSomething(someone: Person) {
    if let universityStudent = someone as? UniversityStudent {
        universityStudent.goToMT()
    } else if let student = someone as? Student {
        student.goToSchool()
    } else if let person = someone as? Person {
        person.breath()
    }
}

doSomething(someone: mike as Person) // 멤버쉽 트레이닝을 갑니다 신남!
doSomething(someone: mike) // 멤버쉽 트레이닝을 갑니다 신남!
doSomething(someone: jenny) // 등교를 합니다
doSomething(someone: yagom) // 숨을 쉽니다


관련문서

The Swift Programming Language - Type Casting





by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓ 블로거에게 공감은 큰 힘이 됩니다 ↓↓↓ 

저작자 표시 비영리 변경 금지
신고

'Swift > 기본문법' 카테고리의 다른 글

프로토콜  (0) 2017.07.17
assert와 guard  (0) 2017.07.13
타입캐스팅  (2) 2017.07.10
옵셔널 체이닝  (2) 2017.07.06
인스턴스의 생성과 소멸  (0) 2017.07.03
상속  (0) 2017.06.29
Posted by yagom

Class vs Struct/Enum

소스코드


열거형과 구조체는 값 타입이며, 클래스는 참조 타입이라는 것이 가장 큰 차이입니다. 또한, 클래스는 상속이 가능하지만 구조체와 열거형은 상속이 불가능합니다.

struct ValueType {
    var property = 1
}

class ReferenceType {
    var property = 1
}

// 첫 번째 구조체 인스턴스
let firstStructInstance = ValueType()
// 두 번째 구조체 인스턴스에 첫 번째 인스턴스 값 복사
var secondStructInstance = firstStructInstance
// 두 번째 구조체 인스턴스 프로퍼티 값 수정
secondStructInstance.property = 2

// 두 번째 구조체 인스턴스는 첫 번째 구조체를 똑같이 복사한 
// 별도의 인스턴스이기 때문에 
// 두 번째 구조체 인스턴스의 프로퍼티 값을 변경해도
// 첫 번째 구조체 인스턴스의 프로퍼티 값에는 영향이 없음
print("first struct instance property : \(firstStructInstance.property)")    // 1
print("second struct instance property : \(secondStructInstance.property)")  // 2


// 클래스 인스턴스 생성 후 첫 번째 참조 생성
let firstClassReference = ReferenceType()
// 두 번째 참조 변수에 첫 번째 참조 할당
let secondClassReference = firstClassReference
secondClassReference.property = 2

// 두 번째 클래스 참조는 첫 번째 클래스 인스턴스를 참조하기 때문에
// 두 번째 참조를 통해 인스턴스의 프로퍼티 값을 변경하면
// 첫 번째 클래스 인스턴스의 프로퍼티 값을 변경하게 됨
print("first class reference property : \(firstClassReference.property)")    // 2
print("second class reference property : \(secondClassReference.property)")  // 2


관련문서

The Swift Programming Language - Enumerations

The Swift Programming Language - Classes and Structures





by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓ 블로거에게 공감은 큰 힘이 됩니다 ↓↓↓ 


저작자 표시 비영리 변경 금지
신고

'Swift > 기본문법' 카테고리의 다른 글

프로퍼티 - Property  (2) 2017.06.26
클로저 - Closure  (0) 2017.06.22
클래스, 구조체, 열거형 비교  (0) 2017.06.19
열거형 - Enumerations  (0) 2017.06.15
클래스  (0) 2017.06.12
구조체  (2) 2017.06.08
Posted by yagom


오늘의 주제

1. 함수

2. 콜렉션 타입 - 배열, 딕셔너리, 세트


안녕하세요, 야곰입니다. 


지난 포스팅에서는 변수와 상수 선언방법 그리고 기초적인 데이터 타입까지 알아봤습니다.


2017/01/23 - [Swift] - Swift란 어떤 언어인가?

2017/01/25 - [Swift] - Swift 기초문법 - 변수, 상수, 기초 데이터 타입


이번에는 스위프트의 함수와 함께 스위프트에서 제공하는 컬렉션 타입에 대해 알아보겠습니다 :)


함수

대부분 함수는 작업의 가장 작은 단위이자 하나의 작은 프로그램이기도 합니다. “하나의 프로 그램은 하나의 큰 함수다”라는 말이 있듯이, 함수는 프로그램을 이루는 주된 요소 중 하나입니다. 스위프트에서 함수는 일급 객체이기 때문에 하나의 값으로도 사용할 수 있습니다. 


스위프트에서 함수는 다른 언어보다 훨씬 다양한 모습으로 존재하며, 코딩 스타일도 여러 가지입니다. 따라서 개인이나 협업자끼리 코딩 규칙을 만들고 함수를 사용하기를 권합니다. 


함수와 메서드



함수의 정의와 호출 

스위프트의 함수는 재정의(오버라이드)와 중복 정의(오버로드)를 모두 지원합니다. 따라서 매개변수의 타입이 다르면 같은 이름의 함수를 여러 개 만들 수 있고, 매개변수의 개수가 달라도 같은이름의 함수를 만들 수 있습니다. 그렇기 때문에 예제 중간중간 이름이 같은 함수를 구현해도 오류가 발생하지 않습니다. 



기본적인 함수의 정의와 호출


스위프트의 함수는 자유도가 굉장히 높은 문법 중 하나입니다. 기본으로 함수의 이름과 매개변수(Parameter), 반환 타입(Return Type) 등을 사용하여 함수를 정의합니다. 

함수를 정의하는 키워드는 func입니다. 함수 이름을 지정해준 후 매개변수는 소괄호( ( ) )로 감싸줍니다. 반환 타입을 명시하기 전에 -> 를 사용하여 어떤 타입이 반환될 것인지 명시해줍니다. 반환을 위한 키워드는 다른 언어처럼 return입니다. 


함수의 기본 형태는 다음과 같습니다. 

func 함수이름(매개변수...) -> 반환타입 { 
    실행 구문 
    return 반환 값 
} 

간단한 함수를 구현해 봅니다. 함수 이름은 hello이며, name이라는 이름의 String 타입 매개변수를 가지며, String 타입의 값을 반환하는 함수입니다. 또, greeting이라는 문자열에 hello 함수의 반환 값을 저장하고 출력합니다.

func hello(name: String) -> String {
    return "Hello \(name)!"
}

let greeting: String = hello(name: "yagom")
print(greeting)   // Hello yagom!

매개변수가 없는 함수

함수에 매개변수가 필요 없다면 매개변수 위치를 공란으로 비워둡니다. 

func helloWorld() -> String { return "Hello, world!" } print(helloWorld()) // Hello, world!


매개변수가 여러 개인 함수 

매개변수가 여러 개 필요한 함수를 정의할 때는 쉼표(,)로 매개변수를 구분합니다. 주의할 점은 함수를 호출할 때, 매개변수 이름을 붙여주고 콜론(:)을 적어준 후 전달인자를 보내준다는 점입니다. 

func sayHello(myName: String, yourName: String) -> String {
    return "Hello \(yourName)! I'm \(myName)"
}

print(sayHello(myName: "yagom", yourName: "eric"))
// Hello eric! I'm yagom

컬렉션 타입

스위프트는 많은 수의 데이터를 묶어서 저장하고 관리할 수 있는 컬렉션 타입을 제공합니다. 컬렉션 타입에는 배열(Array), 딕셔너리(Dictionary), 세트(Set) 등이 있습니다. 이번 포스팅에서는 배열과 딕셔너리에 대해 알아봅니다.

배열


배열은 같은 타입의 데이터를 일렬로 순서대로 저장하는 형태의 컬렉션 타입입니다. 각기 다른 위치에 같은 값이 들어갈 수도 있음을 알아두세요. let 키워드를 사용하여 상수로 선언하면 변경할 수 없는 배열이 되고, var 키워드를 사용하여 변수로 선언해주면 변경 가능한 배열이 됩니다. 실제로 배열을 사용할 때는 Array라는 키워드와 타입 이름의 조합으로 사용합니다. 또, 대괄호로 값을 묶어 Array 타입임을 표현할 수도 있습니다. 이처럼 배열 타입을 선언해줄 수 있는 방법은 다양합니다. 빈 배열은 이니셜라이저 또는 리터럴 문법을 통해 생성해줄 수 있는 데 isEmpty 프로퍼티를 통해 비어있는 배열인지 확인해볼 수 있습니다. 그리고 배열에 몇 개 의 요소가 존재하는지 알고 싶으면 count 프로퍼티를 확인하면 됩니다. 

스위프트의 Array



var names: Array = ["yagom", "chulsoo", "younghee", "yagom"]
// 대괄호를 사용하여 배열임을 표현합니다. 

var names: [String] = ["yagom", "chulsoo", "younghee", "yagom"]
// 위의 선언과 정확히 동일한 표현으로, [String]은 Array의 축약 표현입니다.

var emptyArray: [String] = [String]() 
// String 데이터를 요소로 갖는 빈 배열을 생성합니다. 

var emptyArray: [String] = Array() 
// 위의 선언과 정확히 같은 동작을 하는 코드입니다. 

var emptyArray: [String] = []
// 배열의 타입을 정확히 명시해줬다면 []만으로도 빈 배열을 생성할 수 있습니다.

print(emptyArray.isEmpty)   // true
print(names.count)          // 4 

배열은 각 요소에 인덱스를 통해 접근할 수 있습니다. 인덱스는 0부터 시작합니다. 잘못된 인덱스로 접근하려고 하면 오류가 발생합니다. 

맨 처음과 맨 마지막 요소는 firstlast 프로퍼티를 통해 가져올 수 있습니다. 
index(of:) 메서드를 사용하면 해당 요소의 인덱스를 알아낼 수도 있습니다. 만약, 중복된 요소가 있다면 제일 먼저 발견된 요소의 인덱스를 반환합니다. 
맨 뒤에 요소를 추가하고 싶다면 append(_:) 메서드를 사용합니다. 
중간에 요소를 삽입하고 싶다면 insert(_:at:) 메서드를 사용하면 됩니다. 
요소를 삭제하고 싶다면 remove(_:) 메서드를 사용하게 되는데, 메서드를 사용하면 해당 요소가 삭제된 후 반환됩니다.

print(names[2])     // younghee

names[2] = "jenny"

print(names[2])     // jenny
print(names[4])     // 인덱스의 범위를 벗어났기 때문에 오류가 발생합니다.

names[4] = "elsa"   // 인덱스의 범위를 벗어났기 때문에 오류가 발생합니다.
names.append("elsa")    // 마지막에 elsa가 추가됩니다.

names.append(contentsOf: ["john", "max"]) // 맨 마지막에 john과 max가 추가됩니다. 
names.insert("happy", at: 2) // 인덱스 2에 삽입됩니다. 
names.insert(contentsOf: ["jinhee", "minsoo"], at: 5)
// 인덱스 5의 위치에 jinhee와 minsoo가 삽입됩니다. 

print(names[4]) // yagom
print(names.index(of: "yagom"))     // 0
print(names.index(of: "christal"))  // nil
print(names.first)      // yagom
print(names.last)       // max

let firstItem: String = names.removeFirst()
let lastItem: String = names.removeLast()
let indexZeroItem: String = names.remove(at: 0)

print(firstItem)        // yagom
print(lastItem)         // max
print(indexZeroItem)    // chulsoo
print(names[1 ... 3])   // ["jenny", "yagom", "jinhee"]

  • 중간중간 몇몇 print 함수를 실행하려고 하면 경고를 띄워주는 이유는 해당 메서드의 반환값이 옵셔널이기 때문입니다. 옵셔널에 대해서는 다음 포스팅에서 다룹니다.
  • nil은 ‘없음’을 의미하는 표현입니다.

위의 코드 맨 아래 줄의 names[1 ... 3] 표현은 범위 연산자를 사용하여 names 배열의 일부만 가져온 것입니다. 코드처럼 읽기만 가능한 것이 아니라 names[1 ... 3] = ["A", "B", "C"]와 같이 범위에 맞게 요소를 바꾸는 것도 가능합니다. 스위프트의 배열을 비롯한 컬렉션 타입을 활용할 때 서브스크립트(Subscript) 기능을 많이 사용합니다. 


딕셔너리

딕셔너리는 요소들이 순서 없이 키와 값의 쌍으로 구성되는 컬렉션 타입입니다. 
딕셔너리에 저장되는값은 항상 키와 쌍을 이루게 되는데, 딕셔너리 안에는 키가 하나이거나 여러 개일 수 있습니다. 단, 하나의 딕셔너리 안의 키는 그 안에서는 유일해야 합니다. 쉽게 말해서 아래의 코드에서 “yagom”이라는 키가 두 번 쓰일 수 없다는 뜻입니다. 즉, 딕셔너리에서 키는 값을 대변 하는 유일한 식별자가 되는 것입니다.

let 키워드를 사용하여 상수로 선언하면 변경 불가능한 딕셔너리가 되고, var 키워드를 사용하여 변수로 선언해주면 변경 가능한 딕셔너리가 됩니다. 

딕셔너리는 Dictionary라는 키워드와 키의 타입과 값의 타입 이름의 조합으로 써줍니다. 대괄호로 키와 값의 타입 이름의 쌍을 묶어 딕셔너리 타입임을 표현합니다. 
빈 딕셔너리는 이니셜라이저 또는 리터럴 문법을 통해 생성할 수 있습니다. 
isEmpty 프로퍼티를 통해 비어있는 딕셔너리인지 확인할 수 있습니다. 그리고 count 프로퍼티로 딕셔너리의 요소 개수를 확인할 수 있습니다.

// 키는 String, 값은 Int 타입인 빈 딕셔너리를 생성합니다.
var numberForName: Dictionary = Dictionary()

// 위의 선언과 정확히 동일한 표현입니다.
var numberForName: [String: Int] = [String: Int]()
// [String: Int]는 Dictionary의 축약 표현입니다.

// 딕셔너리의 키와 값 타입을 정확히 명시해줬다면 [:]만으로도 빈 딕셔너리를 생성할 수 있습니다. 
var numberForName: [String: Int] = [:]

var numberForName: [String:Int] = ["yagom":100, "chulsoo":200, "jenny":300]
// 초깃값을 주어 생성해줄 수도 있습니다.

print(numberForName.isEmpty) // false 
print(numberForName.count) // 3

딕셔너리는 각 값에 키를 통해 접근할 수 있습니다. 딕셔너리 내부에서 키는 유일해야 하며, 값은 유일하지 않습니다. 딕셔너리는 배열과는 다르게 딕셔너리 내부에 없는 키로 접근해도 오류가 발생하지 않습니다. 다만 nil을 반환할 뿐이죠. 

특정 키에 해당하는 값을 제거하려면 removeValue(forKey:) 메서드를 사용하면 됩니다. 키에 해당하는 값이 제거된 후 반환됩니다.

print(numberForName["chulsoo"]) // 200
print(numberForName["minji"])   // nil

numberForName["chulsoo"] = 150
print(numberForName["chulsoo"]) // 150

numberForName["max"] = 999      // max라는 키로 999라는 값을 추가해줍니다.
print(numberForName["max"])     // 999

print(numberForName.removeValue(forKey: "yagom"))   // 100
print(numberForName.removeValue(forKey: "yagom"))   // nil
// 위에서 yagom 키에 해당하는 값이 이미 삭제되었으므로 nil이 반환됩니다.


이번에 스위프트의 기초적인 형태의 함수와 컬렉션 데이터 타입에 대해 알아봤습니다. 다음 포스팅에서는 구조체와 클래스에 대해 알아보겠습니다. 

다음 번에 또 뵈어요~ 고맙습니다 :D





by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/

twitter : http://www.twitter.com/yagomSoft ( @yagomsoft )

p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   




저작자 표시 비영리 변경 금지
신고

'Swift > 기본문법' 카테고리의 다른 글

스위프트 시작하기  (0) 2017.05.08
Swift - 프로토콜, 익스텐션  (0) 2017.03.07
Swift - 구조체 클래스  (0) 2017.02.28
Swift - 함수, 콜렉션 타입  (0) 2017.02.06
Swift 기초문법 - 변수, 상수, 기초 데이터 타입  (0) 2017.01.25
Swift란 어떤 언어인가?  (0) 2017.01.23
Posted by yagom


티스토리 툴바