Swift의 함수와 메소드

Preview:

DESCRIPTION

애플사의 새로운 프로그래밍 언어인 Swift 언어에 대해 개발자들의 관심이 커지고 있습니다. 본 발표에서는 실제 예제를 통해서 Swift의 함수와 메소드에 대해 알아보고, 튜플을 이용한 다중 변수 리턴기능과 제너릭등에 대한 재미있는 기능도 알아보겠습니다. 2014년 7월 19일 모바일 앱 개발자 포럼 발표자료를 공유합니다.

Citation preview

Swift의 함수와 메소드

!창원대학교 정보통신공학과 교수 박동규

!http://ivis.cwnu.ac.kr/tc/dongupak

https://www.facebook.com/groups/smartphone.forum/

참고문서

http://lean-tra.github.io/Swift-Korean/

함수 Function• 프로그램의 기본적인 구성요소

• 어떤 작업을 수행하는 문장의 그룹

• 하나의 프로그램은 여러개의 함수들이 모여서 이루어진다

• 프로그램에서 레고 블럭과 같은 요소

• 가독성의 증대, 유지관리가 쉽다.

함수

함수

Swift의 함수

Swift의 함수import Foundation

Swift의 함수import Foundation

Swift의 함수import Foundation

func Add10(num: Int) -> (Int) {

Swift의 함수import Foundation

func Add10(num: Int) -> (Int) { var result = num + 10;

Swift의 함수import Foundation

func Add10(num: Int) -> (Int) { var result = num + 10; return result

Swift의 함수import Foundation

func Add10(num: Int) -> (Int) { var result = num + 10; return result}

Swift의 함수import Foundation

func Add10(num: Int) -> (Int) { var result = num + 10; return result}

Swift의 함수import Foundation

func Add10(num: Int) -> (Int) { var result = num + 10; return result}

var n = 21

Swift의 함수import Foundation

func Add10(num: Int) -> (Int) { var result = num + 10; return result}

var n = 21println("Before Add10(10), n = \(n)")

Swift의 함수import Foundation

func Add10(num: Int) -> (Int) { var result = num + 10; return result}

var n = 21println("Before Add10(10), n = \(n)")

Swift의 함수import Foundation

func Add10(num: Int) -> (Int) { var result = num + 10; return result}

var n = 21println("Before Add10(10), n = \(n)")

n = Add10(n)

Swift의 함수import Foundation

func Add10(num: Int) -> (Int) { var result = num + 10; return result}

var n = 21println("Before Add10(10), n = \(n)")

n = Add10(n)println("After Add10(10), n = \(n)")

Swift의 함수import Foundation

func Add10(num: Int) -> (Int) { var result = num + 10; return result}

var n = 21println("Before Add10(10), n = \(n)")

n = Add10(n)println("After Add10(10), n = \(n)")

Before Add10(10), n = 21

Swift의 함수import Foundation

func Add10(num: Int) -> (Int) { var result = num + 10; return result}

var n = 21println("Before Add10(10), n = \(n)")

n = Add10(n)println("After Add10(10), n = \(n)")

Before Add10(10), n = 21After Add10(10), n = 31

Swift의 함수

Swift의 함수

Swift의 함수함수명

Swift의 함수

Swift의 함수

Swift의 함수매개변수(인자)

Swift의 함수

Swift의 함수

Swift의 함수반환값

Swift의 함수

Swift의 함수

Swift의 함수

함수 몸체

Swift의 함수

Swift의 함수

Swift의 함수

함수 호출

Swift의 함수

함수 호출

다중 반환값

• C/C++/Objective-C/Java 등의 언어에서는 함수가 하나의 리턴값만을 가질수 밖에 없어 불편함.

• 튜플(tuple)을 사용하면 여러 개의 값을 반환할 수 있다.

• swap 함수의 예를 통해 알아보자

swap 함수

swap 함수

swap 함수을

swap 함수을

tuple을 이용하여 받아온다

swap 함수을

tuple을 이용하여 받아온다

튜플 Tuple

• Swift에서 사용하는 Grouping of Values

• 괄호를 사용하여 아이템을 정의함

• 함수에서 매우 유용하게 사용할 수 있음

튜플 Tuple

(1, 2, 3) // (Int, Int, Int)

(3.14, 1.414) // (Double, Double)

(123, “Busan”, “Seagull”) // (Int, String, String)

튜플 Tuple

(1, 2, 3) // (Int, Int, Int)

(3.14, 1.414) // (Double, Double)

(123, “Busan”, “Seagull”) // (Int, String, String)

() 안에 ,(쉼표)를 이용해서 동일한 형, 또는 서로 다음 형의 자료값을 묶어 하나의 자료형으로 취급할 수 있음

튜플 재조합import Foundation !func refreshWebPage() -> (Int, String) { // … return (200, "Success") } !let (statusCode, message) = refreshWebPage() !println("Received \(statusCode): \(message)")

튜플 재조합import Foundation !func refreshWebPage() -> (Int, String) { // … return (200, "Success") } !let (statusCode, message) = refreshWebPage() !println("Received \(statusCode): \(message)")

Received 200: Success

함수 매개변수func greetings1() { println("Hello, Guys!") } !func greetings2(name :String) { println("Hello, \(name)!") } !greetings1() greetings2("Busan Seagulls")

함수 매개변수func greetings1() { println("Hello, Guys!") } !func greetings2(name :String) { println("Hello, \(name)!") } !greetings1() greetings2("Busan Seagulls")

Hello, Guys! Hello, Busan Seagulls!

함수 매개변수func greetings1() { println("Hello, Guys!") } !func greetings2(name :String) { println("Hello, \(name)!") } !greetings1() greetings2("Busan Seagulls")

함수 매개변수func greetings1() { println("Hello, Guys!") } !func greetings2(name :String) { println("Hello, \(name)!") } !greetings1() greetings2("Busan Seagulls")

Hello, Guys! Hello, Busan Seagulls!

함수 매개변수import Foundation

!func greetings1() { println("Hello, Guys!") } !func greetings2(name :String) { println("Hello, \(name)!") } !func greetings3(name :String, message :String) { println("Hello, \(name)! \(message)") } !greetings1() greetings2("Busan Seagulls") greetings3("Park", "Nice to see you!")

Hello, Guys! Hello, Busan Seagulls! Hello, Park! Nice to see you!

C로 만든 Swap 함수#include <stdio.h> !void swap(int *num1, int *num2) { int temp; temp = *num1; *num1 = *num2; *num2 = temp; } !int main(int argc, const char * argv[]) { int n1 = 100, n2 = 200; printf("Before : n1 = %d \n",n1); printf("Before : n2 = %d \n",n2); swap(&n1, &n2); printf("After : n1 = %d \n",n1); printf("After : n2 = %d \n",n2); return 0; }

C로 만든 Swap 함수#include <stdio.h> !void swap(int *num1, int *num2) { int temp; temp = *num1; *num1 = *num2; *num2 = temp; } !int main(int argc, const char * argv[]) { int n1 = 100, n2 = 200; printf("Before : n1 = %d \n",n1); printf("Before : n2 = %d \n",n2); swap(&n1, &n2); printf("After : n1 = %d \n",n1); printf("After : n2 = %d \n",n2); return 0; } 포인터 연산자를 이용하여 외부 변수값에 접근함

C++로 만든 Swap 함수#include <iostream> using namespace std; !void swap(int &num1, int &num2) { int temp; temp = num1; num1 = num2; num2 = temp; } !int main(int argc, const char * argv[]) { int n1 = 100, n2 = 200; cout << "Before : n1 = " << n1 << endl; cout << "Before : n2 = " << n2 << endl; swap(n1, n2); cout << "After : n1 = " << n1 << endl; cout << "After : n2 = " << n2 << endl; ! return 0; }

C++로 만든 Swap 함수#include <iostream> using namespace std; !void swap(int &num1, int &num2) { int temp; temp = num1; num1 = num2; num2 = temp; } !int main(int argc, const char * argv[]) { int n1 = 100, n2 = 200; cout << "Before : n1 = " << n1 << endl; cout << "Before : n2 = " << n2 << endl; swap(n1, n2); cout << "After : n1 = " << n1 << endl; cout << "After : n2 = " << n2 << endl; ! return 0; }

참조 연산자 &를 이용하여 외부 변수값을 참조함

C++로 만든 Swap 함수#include <iostream> using namespace std; !void swap(int &num1, int &num2) { int temp; temp = num1; num1 = num2; num2 = temp; } !int main(int argc, const char * argv[]) { int n1 = 100, n2 = 200; cout << "Before : n1 = " << n1 << endl; cout << "Before : n2 = " << n2 << endl; swap(n1, n2); cout << "After : n1 = " << n1 << endl; cout << "After : n2 = " << n2 << endl; ! return 0; }

참조 연산자 &를 이용하여 외부 변수값을 참조함

C++로 만든 Swap 함수#include <iostream> using namespace std; !void swap(int &num1, int &num2) { int temp; temp = num1; num1 = num2; num2 = temp; } !int main(int argc, const char * argv[]) { int n1 = 100, n2 = 200; cout << "Before : n1 = " << n1 << endl; cout << "Before : n2 = " << n2 << endl; swap(n1, n2); cout << "After : n1 = " << n1 << endl; cout << "After : n2 = " << n2 << endl; ! return 0; }

참조 연산자 &를 이용하여 외부 변수값을 참조함

Swift로 만든 Swap 함수1import Foundation !func swap(n1:Int, n2:Int) -> (Int, Int){ return (n2, n1) } !var n1 = 100 var n2 = 200 !println("Before : n1 = \(n1)") println("Before : n2 = \(n2)") !(n1, n2) = swap(n1, n2) !println("After : n1 = \(n1)") println("After : n2 = \(n2)")

Swift로 만든 Swap 함수1import Foundation !func swap(n1:Int, n2:Int) -> (Int, Int){ return (n2, n1) } !var n1 = 100 var n2 = 200 !println("Before : n1 = \(n1)") println("Before : n2 = \(n2)") !(n1, n2) = swap(n1, n2) !println("After : n1 = \(n1)") println("After : n2 = \(n2)")

튜플을 반환하는 방식으로 간단하게 구현가능

Swift로 만든 Swap 함수1import Foundation !func swap(n1:Int, n2:Int) -> (Int, Int){ return (n2, n1) } !var n1 = 100 var n2 = 200 !println("Before : n1 = \(n1)") println("Before : n2 = \(n2)") !(n1, n2) = swap(n1, n2) !println("After : n1 = \(n1)") println("After : n2 = \(n2)")

튜플을 반환하는 방식으로 간단하게 구현가능

Swift로 만든 Swap 함수2import Foundation !func swap(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA } !var n1 = 100 var n2 = 200 !println("Before : n1 = \(n1)") println("Before : n2 = \(n2)") !swap(&n1, &n2) !println("After : n1 = \(n1)") println("After : n2 = \(n2)")

Swift로 만든 Swap 함수2import Foundation !func swap(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA } !var n1 = 100 var n2 = 200 !println("Before : n1 = \(n1)") println("Before : n2 = \(n2)") !swap(&n1, &n2) !println("After : n1 = \(n1)") println("After : n2 = \(n2)")

Swift로 만든 Swap 함수2import Foundation !func swap(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA } !var n1 = 100 var n2 = 200 !println("Before : n1 = \(n1)") println("Before : n2 = \(n2)") !swap(&n1, &n2) !println("After : n1 = \(n1)") println("After : n2 = \(n2)")

Swift로 만든 Swap 함수2import Foundation !func swap(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA } !var n1 = 100 var n2 = 200 !println("Before : n1 = \(n1)") println("Before : n2 = \(n2)") !swap(&n1, &n2) !println("After : n1 = \(n1)") println("After : n2 = \(n2)")

inout과 & 연산자를 사용하여 외부값을 참조할 수 있음

inout

• 매개변수 중에서 함수내에서 변경된 매개변수가 함수 호출이 종료된 시점에서도 계속되기를 원한다면 inout 키워드를 파라메터 정의할 때 사용한다

• 파라메터의 값은 함수 안으로 전달되어 변경되고, 함수에서 나와서 원래의 값을 대체함

• 인수를 입출력 파라메터로 넘길때 변수의 이름 앞에 앰퍼샌드(&)를 붙인다

Swift로 만든 Swap

import Foundation !var n1 = 100 var n2 = 200 !println("Before : n1 = \(n1)") println("Before : n2 = \(n2)") !(n1, n2) = (n2, n1) // 튜플사용 !println("After : n1 = \(n1)") println("After : n2 = \(n2)")

Swift로 만든 Swap

import Foundation !var n1 = 100 var n2 = 200 !println("Before : n1 = \(n1)") println("Before : n2 = \(n2)") !(n1, n2) = (n2, n1) // 튜플사용 !println("After : n1 = \(n1)") println("After : n2 = \(n2)")

Swift로 만든 Swap

import Foundation !var n1 = 100 var n2 = 200 !println("Before : n1 = \(n1)") println("Before : n2 = \(n2)") !(n1, n2) = (n2, n1) // 튜플사용 !println("After : n1 = \(n1)") println("After : n2 = \(n2)")

!(Int, Int) 튜플을 (Int, Int) 튜플에 복사함

함수 레이블

함수 레이블 func join(s1: String, s2: String, joiner: String) -> String { return s1 + joiner + s2 }

함수 레이블 func join(s1: String, s2: String, joiner: String) -> String { return s1 + joiner + s2 }

join("hello", "world", ", ")

함수 레이블 func join(s1: String, s2: String, joiner: String) -> String { return s1 + joiner + s2 }

join("hello", "world", ", ")

vs

함수 레이블 func join(s1: String, s2: String, joiner: String) -> String { return s1 + joiner + s2 }

join("hello", "world", ", ")

vs func join(string s1: String, toString s2: String, withJoiner joiner: String) -> String { return s1 + joiner + s2 }

함수 레이블 func join(s1: String, s2: String, joiner: String) -> String { return s1 + joiner + s2 }

join("hello", "world", ", ")

vs func join(string s1: String, toString s2: String, withJoiner joiner: String) -> String { return s1 + joiner + s2 }

join(string: "hello", toString: "world", withJoiner: ", ")

함수 레이블 func join(s1: String, s2: String, joiner: String) -> String { return s1 + joiner + s2 }

join("hello", "world", ", ")

vs func join(string s1: String, toString s2: String, withJoiner joiner: String) -> String { return s1 + joiner + s2 }

join(string: "hello", toString: "world", withJoiner: ", ")

join 함수를 통해 매개변수로 입력된 String을 조합할 수 있다 레이블링을 통해 매개변수의 역할을 명확하게 이해할 수 있다.

Objective-C와의 호환성을 확보할 수 있다

variadic 함수• 함수구문에서 함수에 전달되는 매개변수의 개수를 정확하게 알 수 없을 경우에 사용하는 문법이 적용된 함수

func arithmeticMean(numbers: Double...) -> Double { var total: Double = 0 for number in numbers { total += number } return total / Double(numbers.count) }

arithmeticMean(1, 2, 3, 4, 5) // 다섯 정수의 산술평균 3.0을 반환함 arithmeticMean(3, 8, 19) // 3,8,19의 산술평균 10.0을 반환함

variadic 함수• 함수구문에서 함수에 전달되는 매개변수의 개수를 정확하게 알 수 없을 경우에 사용하는 문법이 적용된 함수

func arithmeticMean(numbers: Double...) -> Double { var total: Double = 0 for number in numbers { total += number } return total / Double(numbers.count) }

arithmeticMean(1, 2, 3, 4, 5) // 다섯 정수의 산술평균 3.0을 반환함 arithmeticMean(3, 8, 19) // 3,8,19의 산술평균 10.0을 반환함

함수 타입•함수타입의 상수나 변수를 만들어 함수를 할당할 수 있음

두 개의 Int 값을 매개변수로 취하며 Int 값을 반환하는 함수 타입 변수 mathFuntion을 선언하고, 이 변수가 addTwoInts 함수를 참조(refer)하도록 한다.

!var mathFunction: (Int, Int) -> Int = addTwoInts

함수 타입import Foundation !func addTwoInts(a: Int, b: Int) -> Int { return a + b } !var mathFunction: (Int, Int) -> Int = addTwoInts !println("Result: \(mathFunction(2, 3))")

Result: 5

함수 타입 변수 mathFunction

함수 타입import Foundation !func addTwoInts(a: Int, b: Int) -> Int { return a + b } !var mathFunction: (Int, Int) -> Int = addTwoInts !println("Result: \(mathFunction(2, 3))")

Result: 5

함수 타입 변수 mathFunction

Swift 언어의 함수 타입import Foundation !func addTwoInts(a: Int, b: Int) -> Int { return a + b } !var mathFunction: (Int, Int) -> Int = addTwoInts var newMathFunction: (Int, Int) -> Int !newMathFunction = mathFunction println("Result: \(mathFunction(2, 3))") println("Result: \(newMathFunction(3, 3))")

Result: 5 Result: 6

두 개의 Int 값을 취하며 Int 값을 반환하는 함수 타입 변수 mathFuntion을 newMathFunction 변수가 참조한다

C 언어의 함수 타입#include <stdio.h> !int addTwoInts(int a, int b) { return a + b; } !int main(int argc, const char * argv[]) { int (*mathFunction)(int, int) = &addTwoInts; int (*newMathFunction)(int, int); newMathFunction = mathFunction; printf("Result : %d\n", (*mathFunction)(2,3)); printf("Result : %d\n", (*newMathFunction)(3,3)); return 0; }

Result: 5 Result: 6

C 언어의 함수 타입

… int addTwoInts(int a, int b) { return a + b; } !int main(int argc, const char * argv[]) { int (*mathFunction)(int, int) = &addTwoInts; int (*newMathFunction)(int, int); newMathFunction = mathFunction; …

C 언어의 함수 타입

… int addTwoInts(int a, int b) { return a + b; } !int main(int argc, const char * argv[]) { int (*mathFunction)(int, int) = &addTwoInts; int (*newMathFunction)(int, int); newMathFunction = mathFunction; …

C 언어의 함수 타입

… int addTwoInts(int a, int b) { return a + b; } !int main(int argc, const char * argv[]) { int (*mathFunction)(int, int) = &addTwoInts; int (*newMathFunction)(int, int); newMathFunction = mathFunction; …

C 언어의 함수

C 언어의 함수 타입

… int addTwoInts(int a, int b) { return a + b; } !int main(int argc, const char * argv[]) { int (*mathFunction)(int, int) = &addTwoInts; int (*newMathFunction)(int, int); newMathFunction = mathFunction; …

C 언어의 함수

C 언어의 함수 타입

… int addTwoInts(int a, int b) { return a + b; } !int main(int argc, const char * argv[]) { int (*mathFunction)(int, int) = &addTwoInts; int (*newMathFunction)(int, int); newMathFunction = mathFunction; …

C 언어의 함수 타입

… int addTwoInts(int a, int b) { return a + b; } !int main(int argc, const char * argv[]) { int (*mathFunction)(int, int) = &addTwoInts; int (*newMathFunction)(int, int); newMathFunction = mathFunction; …

C 언어의 함수 타입

… int addTwoInts(int a, int b) { return a + b; } !int main(int argc, const char * argv[]) { int (*mathFunction)(int, int) = &addTwoInts; int (*newMathFunction)(int, int); newMathFunction = mathFunction; …

함수 포인터

C 언어의 함수 타입

… int addTwoInts(int a, int b) { return a + b; } !int main(int argc, const char * argv[]) { int (*mathFunction)(int, int) = &addTwoInts; int (*newMathFunction)(int, int); newMathFunction = mathFunction; …

함수 포인터

C 언어의 함수 타입

… int addTwoInts(int a, int b) { return a + b; } !int main(int argc, const char * argv[]) { int (*mathFunction)(int, int) = &addTwoInts; int (*newMathFunction)(int, int); newMathFunction = mathFunction; …

C 언어의 함수 타입

… int addTwoInts(int a, int b) { return a + b; } !int main(int argc, const char * argv[]) { int (*mathFunction)(int, int) = &addTwoInts; int (*newMathFunction)(int, int); newMathFunction = mathFunction; …

C 언어의 함수 타입

… int addTwoInts(int a, int b) { return a + b; } !int main(int argc, const char * argv[]) { int (*mathFunction)(int, int) = &addTwoInts; int (*newMathFunction)(int, int); newMathFunction = mathFunction; …

함수 포인터

C 언어의 함수 타입

… int addTwoInts(int a, int b) { return a + b; } !int main(int argc, const char * argv[]) { int (*mathFunction)(int, int) = &addTwoInts; int (*newMathFunction)(int, int); newMathFunction = mathFunction; …

함수 포인터

C 언어의 함수 타입

… int addTwoInts(int a, int b) { return a + b; } !int main(int argc, const char * argv[]) { int (*mathFunction)(int, int) = &addTwoInts; int (*newMathFunction)(int, int); newMathFunction = mathFunction; …

함수 포인터

함수 포인터를 다른 함수 포인터에 복사할 수 있음

함수를 파라메터로 사용

함수를 파라메터로 사용

func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) { println("Result: \(mathFunction(a, b))") } printMathResult(addTwoInts, 3, 5) // prints "Result: 8"

함수를 파라메터로 사용

func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) { println("Result: \(mathFunction(a, b))") } printMathResult(addTwoInts, 3, 5) // prints "Result: 8"

함수를 파라메터로 사용

func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) { println("Result: \(mathFunction(a, b))") } printMathResult(addTwoInts, 3, 5) // prints "Result: 8"

함수를 파라메터로 사용

func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) { println("Result: \(mathFunction(a, b))") } printMathResult(addTwoInts, 3, 5) // prints "Result: 8"

Result: 8

함수의 반환func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 }

func chooseStepFunction(backwards: Bool) -> (Int) -> Int { return backwards ? stepBackward : stepForward }

함수의 반환func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 }

func chooseStepFunction(backwards: Bool) -> (Int) -> Int { return backwards ? stepBackward : stepForward }

Int형 값을 매개변수로 받아 Int 값을 반환하는 함수

함수의 반환func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 }

func chooseStepFunction(backwards: Bool) -> (Int) -> Int { return backwards ? stepBackward : stepForward }

Int형 값을 매개변수로 받아 Int 값을 반환하는 함수

Int형 값을 매개변수로 받아 Int 값을 반환하는 함수

함수의 반환func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 }

func chooseStepFunction(backwards: Bool) -> (Int) -> Int { return backwards ? stepBackward : stepForward }

Int형 값을 매개변수로 받아 Int 값을 반환하는 함수

Int형 값을 매개변수로 받아 Int 값을 반환하는 함수

함수의 반환func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 }

func chooseStepFunction(backwards: Bool) -> (Int) -> Int { return backwards ? stepBackward : stepForward }

반환형- Int형을 매개변수로 받아 Int 값을 반환하는 함수

Int형 값을 매개변수로 받아 Int 값을 반환하는 함수

Int형 값을 매개변수로 받아 Int 값을 반환하는 함수

함수의 반환func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 }

func chooseStepFunction(backwards: Bool) -> (Int) -> Int { return backwards ? stepBackward : stepForward }

반환형- Int형을 매개변수로 받아 Int 값을 반환하는 함수

Int형 값을 매개변수로 받아 Int 값을 반환하는 함수

Int형 값을 매개변수로 받아 Int 값을 반환하는 함수

함수의 반환func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 }

func chooseStepFunction(backwards: Bool) -> (Int) -> Int { return backwards ? stepBackward : stepForward }

반환형- Int형을 매개변수로 받아 Int 값을 반환하는 함수

Int형 값을 매개변수로 받아 Int 값을 반환하는 함수

Int형 값을 매개변수로 받아 Int 값을 반환하는 함수

함수의 반환func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 }

func chooseStepFunction(backwards: Bool) -> (Int) -> Int { return backwards ? stepBackward : stepForward } 매개변수 backwards가 true이면

stepBackward 함수가, false이면 stepForward 함수가 반환된다

반환형- Int형을 매개변수로 받아 Int 값을 반환하는 함수

Int형 값을 매개변수로 받아 Int 값을 반환하는 함수

Int형 값을 매개변수로 받아 Int 값을 반환하는 함수

중첩 함수•함수 내부에 다른 함수를 중첩할 수 있다

중첩 함수•함수 내부에 다른 함수를 중첩할 수 있다func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 }

중첩 함수•함수 내부에 다른 함수를 중첩할 수 있다

func chooseStepFunction(backwards: Bool) -> (Int) -> Int { !!!!!}

func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 }

중첩 함수•함수 내부에 다른 함수를 중첩할 수 있다

func chooseStepFunction(backwards: Bool) -> (Int) -> Int { !!!!!}

func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 }

중첩 함수•함수 내부에 다른 함수를 중첩할 수 있다

func chooseStepFunction(backwards: Bool) -> (Int) -> Int { !!!!!}

중첩 함수•함수 내부에 다른 함수를 중첩할 수 있다

func chooseStepFunction(backwards: Bool) -> (Int) -> Int { !!!!!}

func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 } return backwards ? stepBackward : stepForward

제너릭스 Generics

• 함수의 자료형에 상관없이 일관된 알고리즘만으로 효율적으로 함수 작성이 가능함

• Swift의 많은 기본 라이브러리들이 제너릭으로 작성되어 있다. 예) Array, Dictionary 타입등

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) {

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA }

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA }func swapTwoDoubles(inout a: Double, inout b: Double) {

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA }func swapTwoDoubles(inout a: Double, inout b: Double) { let temporaryA = a

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA }func swapTwoDoubles(inout a: Double, inout b: Double) { let temporaryA = a a = b

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA }func swapTwoDoubles(inout a: Double, inout b: Double) { let temporaryA = a a = b b = temporaryA

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA }func swapTwoDoubles(inout a: Double, inout b: Double) { let temporaryA = a a = b b = temporaryA }

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA }

func swapTwoStrings(inout a: String, inout b: String) {

func swapTwoDoubles(inout a: Double, inout b: Double) { let temporaryA = a a = b b = temporaryA }

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA }

func swapTwoStrings(inout a: String, inout b: String) { let temporaryA = a

func swapTwoDoubles(inout a: Double, inout b: Double) { let temporaryA = a a = b b = temporaryA }

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA }

func swapTwoStrings(inout a: String, inout b: String) { let temporaryA = a a = b

func swapTwoDoubles(inout a: Double, inout b: Double) { let temporaryA = a a = b b = temporaryA }

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA }

func swapTwoStrings(inout a: String, inout b: String) { let temporaryA = a a = b b = temporaryA

func swapTwoDoubles(inout a: Double, inout b: Double) { let temporaryA = a a = b b = temporaryA }

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA }

func swapTwoStrings(inout a: String, inout b: String) { let temporaryA = a a = b b = temporaryA }

func swapTwoDoubles(inout a: Double, inout b: Double) { let temporaryA = a a = b b = temporaryA }

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA }

func swapTwoStrings(inout a: String, inout b: String) { let temporaryA = a a = b b = temporaryA }

func swapTwoDoubles(inout a: Double, inout b: Double) { let temporaryA = a a = b b = temporaryA }

제너릭스• swap 함수의 값이 Int, Double, String과 같이 다양하다func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a = b b = temporaryA }

func swapTwoStrings(inout a: String, inout b: String) { let temporaryA = a a = b b = temporaryA }

func swapTwoDoubles(inout a: Double, inout b: Double) { let temporaryA = a a = b b = temporaryA }

매개변수는 다르지만 함수의 로직은 동일함 자료형 개수 만큼의 함수가 필요하다. 매우 불편하다

제너릭 함수

제너릭 함수func swapTwoValues<T>(inout a: T, inout b: T) { let temporaryA = a a = b b = temporaryA }

제너릭 함수func swapTwoValues<T>(inout a: T, inout b: T) { let temporaryA = a a = b b = temporaryA }

하나의 함수를 통해서 모든 종류의 자료형에 대한 알고리즘을 만들 수 있다.

제너릭 함수func swapTwoValues<T>(inout a: T, inout b: T) { let temporaryA = a a = b b = temporaryA }

var someInt = 3 var anotherInt = 107 swapTwoValues(&someInt, &anotherInt) // someInt is now 107, and anotherInt is now 3 !var someString = "hello" var anotherString = "world" swapTwoValues(&someString, &anotherString) // someString is now "world", and anotherString is now "hello"

하나의 함수를 통해서 모든 종류의 자료형에 대한 알고리즘을 만들 수 있다.

제너릭 함수func repeat<ItemType>(item: ItemType, times: Int) -> ItemType[] { var result = ItemType[]() for i in 0..times { result += item } return result } var repeat_knock = repeat("knock", 4) var repeat_ten = repeat(10, 4) !println("repeat_knock = \(repeat_knock)") println("repeat_ten = \(repeat_ten)")

제너릭 함수func repeat<ItemType>(item: ItemType, times: Int) -> ItemType[] { var result = ItemType[]() for i in 0..times { result += item } return result } var repeat_knock = repeat("knock", 4) var repeat_ten = repeat(10, 4) !println("repeat_knock = \(repeat_knock)") println("repeat_ten = \(repeat_ten)")

repeat_knock = [knock, knock, knock, knock] repeat_ten = [10, 10, 10, 10]

메소드 Method

• 메소드는 클래스나 구조체 타입에 의존적인 함수로 클래스와 구조체의 인스턴스는 메소드를 정의할 수 있다.

• 또한 타입 자체에 관여하는 타입 메소드를 정의할 수 있다

메소드class Counter { var count = 0 func increment() { count++ } func incrementBy(amount: Int) { count += amount } func reset() { count = 0 } }

let counter = Counter() // 초기 counter값은 0입니다 counter.increment() // counter값은 이제 1입니다 counter.incrementBy(5) // counter값은 이제 6입니다 counter.reset() // counter값은 이제 0입니다

메소드와 레이블

메소드와 레이블함수

메소드와 레이블

import Foundation !func say(name:String, msg:String) { println("\(name) say \(msg)") } !say("Henry","Hi,Swift")

함수

메소드와 레이블

import Foundation !func say(name:String, msg:String) { println("\(name) say \(msg)") } !say("Henry","Hi,Swift")

함수 메소드

메소드와 레이블

import Foundation !func say(name:String, msg:String) { println("\(name) say \(msg)") } !say("Henry","Hi,Swift")

import Foundation !class Hello { var name: String = "" func say(name:String, msg:String){ println("\(name) say \(msg)") } } !var hello = Hello() hello.say("Henry", "Hi,Swift")

함수 메소드

메소드와 레이블

import Foundation !func say(name:String, msg:String) { println("\(name) say \(msg)") } !say("Henry","Hi,Swift")

import Foundation !class Hello { var name: String = "" func say(name:String, msg:String){ println("\(name) say \(msg)") } } !var hello = Hello() hello.say("Henry", "Hi,Swift")

함수 메소드

메소드와 레이블

import Foundation !func say(name:String, msg:String) { println("\(name) say \(msg)") } !say("Henry","Hi,Swift")

import Foundation !class Hello { var name: String = "" func say(name:String, msg:String){ println("\(name) say \(msg)") } } !var hello = Hello() hello.say("Henry", "Hi,Swift")

함수 메소드

메소드와 레이블

• 함수의 경우 매개변수마다 레이블을 달 필요는 없다.

• 메소드의 경우 두번째 이상의 레이블에 대해서는 반드시 레이블을 달아야 한다

• Objective-C의 영향을 받은 것

• 매개변수의 역할을 정확하게 알 수 있어, 에러를 줄일 수 있다.

메소드와 레이블

• 함수의 경우 매개변수마다 레이블을 달 필요는 없다.

• 메소드의 경우 두번째 이상의 레이블에 대해서는 반드시 레이블을 달아야 한다

• Objective-C의 영향을 받은 것

• 매개변수의 역할을 정확하게 알 수 있어, 에러를 줄일 수 있다.

메소드

메소드와 레이블

• 함수의 경우 매개변수마다 레이블을 달 필요는 없다.

• 메소드의 경우 두번째 이상의 레이블에 대해서는 반드시 레이블을 달아야 한다

• Objective-C의 영향을 받은 것

• 매개변수의 역할을 정확하게 알 수 있어, 에러를 줄일 수 있다.

import Foundation !class Hello { var name: String = "" func say(name:String, msg:String){ println("\(name) say \(msg)") } } !var hello = Hello() hello.say("Henry", msg:"Hi,Swift")

메소드

메소드와 레이블

• 함수의 경우 매개변수마다 레이블을 달 필요는 없다.

• 메소드의 경우 두번째 이상의 레이블에 대해서는 반드시 레이블을 달아야 한다

• Objective-C의 영향을 받은 것

• 매개변수의 역할을 정확하게 알 수 있어, 에러를 줄일 수 있다.

import Foundation !class Hello { var name: String = "" func say(name:String, msg:String){ println("\(name) say \(msg)") } } !var hello = Hello() hello.say("Henry", msg:"Hi,Swift")

Henry say Hi,Swift

메소드

레이블

class Counter { var count: Int = 0 func incrementBy(amount: Int, numberOfTimes: Int) { count += amount * numberOfTimes } }

let counter = Counter() Counter.incrementBy(5, numberOfTimes: 3) // Counter value is now 15

레이블

class Counter { var count: Int = 0 func incrementBy(amount: Int, numberOfTimes: Int) { count += amount * numberOfTimes } }

let counter = Counter() Counter.incrementBy(5, numberOfTimes: 3) // Counter value is now 15

메소드의 매개변수인 numberOfTime 를 호출시의 레이블로 사용할 수 있다. 이 레이블을 통해 두번째 매개변수의 목적을 명확하게 알 수 있다

레이블

class Counter { var count: Int = 0 func incrementBy(amount: Int, #numberOfTimes: Int) { count += amount * numberOfTimes } }

let counter = Counter() Counter.incrementBy(5, numberOfTimes: 3) // Counter value is now 15

레이블

class Counter { var count: Int = 0 func incrementBy(amount: Int, #numberOfTimes: Int) { count += amount * numberOfTimes } }

let counter = Counter() Counter.incrementBy(5, numberOfTimes: 3) // Counter value is now 15

numberOfTime 와 같은 매개변수 이름을 레이블로 사용할 수 있다.(디폴트 매개변수명) 이때 매개변수의 이름에 #을 붙여서 이를 명시적으로 만들 수 있다-Objective-C의 문법과 동일함.

레이블import Foundation !class Hello { … func say(name:String, msg:String, ofCount n:Int){ for index in 1...n { println("\(name) say \(msg)") } } } … hello.say("Henry", msg:"Hi,Swift", ofCount:3)

레이블import Foundation !class Hello { … func say(name:String, msg:String, ofCount n:Int){ for index in 1...n { println("\(name) say \(msg)") } } } … hello.say("Henry", msg:"Hi,Swift", ofCount:3)

위 메소드의 ofCount는 레이블이며, n은 매개변수이다 레이블과 매개변수는 다를 수 있다

함수 레이블(익명 레이블)import Foundation !class Hello { … func say(name:String, _ msg:String, _ n:Int){ for index in 1...n { println("\(name) say \(msg)") } } } … hello.say("Henry","Hi,Swift", 3)

함수 레이블(익명 레이블)

레이블 대신 _(언더바)를 사용하여 레이블을 생력할 수 있다.

import Foundation !class Hello { … func say(name:String, _ msg:String, _ n:Int){ for index in 1...n { println("\(name) say \(msg)") } } } … hello.say("Henry","Hi,Swift", 3)

self 속성• self는 내재적인 속성으로 모든 인스턴스가 가지고 있다.

• self는 인스턴스 자체를 지시한다

func increment() { self.count++ }

self 속성• self는 내재적인 속성으로 모든 인스턴스가 가지고 있다.

• self는 인스턴스 자체를 지시한다

func increment() { self.count++ }

위와같이 메소드에 self를 반드시 달 필요는 없으며 self. 가 없을 경우 Swift는 현재 인스턴스의 메소드나 속성을 가리키는 것으로 가정한다

self 속성

self 속성 struct Point { var x = 0.0, y = 0.0 func isToTheRightOfX(x: Double) -> Bool { return x > x } }

self 속성 struct Point { var x = 0.0, y = 0.0 func isToTheRightOfX(x: Double) -> Bool { return x > x } }

self.

self 속성 struct Point { var x = 0.0, y = 0.0 func isToTheRightOfX(x: Double) -> Bool { return x > x } }

self.

위와 같은 메소드에서 x > x라고 할 경우 x가 매개변수 x인지 Point의 멤버 변수 x인지를 알 수 없다 self.x > x 를 통해서 self.x 는 멤버변수 x임을 알 수 있다

mutating 키워드 struct Point { var x = 0.0, y = 0.0 mutating func moveByX(deltaX: Double, y deltaY: Double) { x += deltaX y += deltaY } } var somePoint = Point(x: 1.0, y: 1.0) somePoint.moveByX(2.0, y: 3.0) println("The point is now at (\(somePoint.x), \(somePoint.y))")

mutating 키워드 struct Point { var x = 0.0, y = 0.0 mutating func moveByX(deltaX: Double, y deltaY: Double) { x += deltaX y += deltaY } } var somePoint = Point(x: 1.0, y: 1.0) somePoint.moveByX(2.0, y: 3.0) println("The point is now at (\(somePoint.x), \(somePoint.y))")

메소드 moveByX를 통해 인스턴스의 속성을 변경시키고자 할 경우 mutating 키워드를 사용하여 인스턴스의 속성 x, y를 변경

용어정리

• C나 C++와 같은 프로그래밍 언어에서는 일반적으로 클래스의 인스턴스를 객체(오브젝트)라고 한다.

• Swift는 다른 언어와 달리 클래스와 구조체의 기능이 유사하다. 클래스와 구조체의 인스턴스 모두 함수를 가질 수 있다.

• 이 때문에 Swift에서는 객체라는 용어보다 일반적인 인스턴스라는 용어를 사용한다

클래스와 구조체

•클래스(class)와 구조체(struct)는 모두 범용적이고 가변적인 프로그램의 구성 성분이다

• 클래스와 구조체 모두 상수, 변수, 함수를 가지는데, 이때 문법은 동일하다.

클래스와 구조체의 유사성•값을 저장할 속성을 정의한다

• 기능을 위한 메소드를 정의한다

• subscript 구문을 사용하여 이들의 값에 접근할 수 있도록 subscript를 제공한다

• 초기상태를 설정하기 위한 초기설정자를 제공한다

• 기본 구현내용을 확장하기 위한 기능을 제공한다

• 어떤 표준적인 기능을 제공하는 프로토콜을 따른다

클래스와 구조체의 차이점•클래스는 구조체가 가지지 못한 다음 기능을 가진다

• 한 클래스의 특성을 상속받는 기능이 가능하다

• 클래스 인스턴스를 형을 검사하고 번영하여 런타임시에 형변환을 할 수 있다

• 할당된 임의의 리소스를 해지하는 deinitializer를 가진다

• 클래스 인스턴스는 참조 카운터를 하나이상 허용한다

정리• Swift의 함수는 C언어의 함수보다 간결하면서도 쉽다

• 튜플타입을 사용하여 함수를 유연성있게 사용할 수 있다

• Objective-C의 레이블 기능을 메소드에서도 사용할 수 있도록 하여 호환성을 확보하였다

• 제너릭 타입은 자료형에 무관한 유연한 코딩이 가능하다

• Swift의 철학은 간결하면서도 안전한 프로그램을 추구한다

Q & Adongupak@gmail.com

Recommended