Post on 15-Apr-2017
Swift 3 : Subscript, Init, Type Casting
군산대학교 컴퓨터정보통신공학부 컴퓨터정보공학전공
남 광 우
kwnam@kunsan.ac.kr
Swift 3 Tour and Language Guide by Apple꼼꼼한재은씨의 Swift 2 프로그래밍
Initialization• init() 을이용한초기화
• Stored Properties초기화• Initializer
• 초기화예
init() {// 초기화구문
}
struct Fahrenheit {var temperature: Doubleinit() {temperature = 32.0
}}var f = Fahrenheit()print("The default temperature is \(f.temperature)° Fahrenheit")// Prints "The default temperature is 32.0° Fahrenheit"
Initialization• Customizing Initialization
• 사용
struct Celsius {var temperatureInCelsius: Doubleinit(fromFahrenheit fahrenheit: Double) {temperatureInCelsius = (fahrenheit ‐ 32.0) / 1.8
}init(fromKelvin kelvin: Double) {temperatureInCelsius = kelvin ‐ 273.15
}}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)// boilingPointOfWater.temperatureInCelsius is 100.0let freezingPointOfWater = Celsius(fromKelvin: 273.15)// freezingPointOfWater.temperatureInCelsius is 0.0
Initialization• Parameter Name과 Argument Label
• 사용
struct Color {let red, green, blue: Doubleinit(red: Double, green: Double, blue: Double) {self.red = redself.green = greenself.blue = blue
}init(white: Double) {red = whitegreen = whiteblue = white
}}
let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)let halfGray = Color(white: 0.5)
Initialization• Parameter Name without Argument Label
• 사용
struct Celsius {var temperatureInCelsius: Doubleinit(fromFahrenheit fahrenheit: Double) {temperatureInCelsius = (fahrenheit ‐ 32.0) / 1.8
}init(fromKelvin kelvin: Double) {temperatureInCelsius = kelvin ‐ 273.15
}init(_ celsius: Double) {temperatureInCelsius = celsius
}}
let bodyTemperature = Celsius(37.0)// bodyTemperature.temperatureInCelsius is 37.0
Initialization• Optional Property 타입
• optional 타입은 default로 nil 설정
• 사용
class SurveyQuestion {var text: Stringvar response: String?init(text: String) {self.text = text
}func ask() {print(text)
}}
let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")cheeseQuestion.ask()// Prints "Do you like cheese?"cheeseQuestion.response = "Yes, I do like cheese."
Initialization•초기화동안상수초기화
• 예
class SurveyQuestion {let text: Stringvar response: String?init(text: String) {self.text = text
}func ask() {print(text)
}}
let beetsQuestion = SurveyQuestion(text: "How about beets?")beetsQuestion.ask()// Prints "How about beets?"beetsQuestion.response = "I also like beets. (But not with cheese.)"
초기화후변경불가
Initialization• Default Property
• Default Initializer• init이없으면 default 값으로설정
struct Fahrenheit {var temperature = 32.0
}
class ShoppingListItem {var name: String?var quantity = 1var purchased = false
}var item = ShoppingListItem()
Initialization• Struct를위한Memberwise Initializer
struct Size {var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0, height: 2.0)
Initialization•대표 Initializer 를이용한초기화
struct Rect {var origin = Point()var size = Size()init() {}init(origin: Point, size: Size) {self.origin = originself.size = size
}init(center: Point, size: Size) {let originX = center.x ‐ (size.width / 2)let originY = center.y ‐ (size.height / 2)self.init(origin: Point(x: originX, y: originY), size: size)
}} struct Size {
var width = 0.0, height = 0.0}struct Point {var x = 0.0, y = 0.0
}
Initialization• Initializer Delegation이용한초기화(계속)
• () 사용
• (origin, size)
• (center, size)
let basicRect = Rect()// basicRect's origin is (0.0, 0.0) and its size is (0.0, 0.0)
let originRect = Rect(origin: Point(x: 2.0, y: 2.0),size: Size(width: 5.0, height: 5.0))
// originRect's origin is (2.0, 2.0) and its size is (5.0, 5.0)
let centerRect = Rect(center: Point(x: 4.0, y: 4.0),size: Size(width: 3.0, height: 3.0))
// centerRect's origin is (2.5, 2.5) and its size is (3.0, 3.0)
Class Inheritance와 초기화
• Designated Initializer와 Convenience Initializer• Designated Initializer
• Convenience Initializer
init( parameters ) {
}
convenience init( parameters ) {
}
Class Inheritance와 초기화
class Vehicle {var numberOfWheels = 0var description: String {return "\(numberOfWheels) wheel(s)"
}}
let vehicle = Vehicle()print("Vehicle: \(vehicle.description)")// Vehicle: 0 wheel(s)
class Bicycle: Vehicle {override init() {super.init()numberOfWheels = 2
}}
• Initializer 예
Class Inheritance와 초기화
class Food {var name: Stringinit(name: String) {self.name = name
}convenience init() {self.init(name: "[Unnamed]")
}}
let namedMeat = Food(name: "Bacon")// namedMeat's name is "Bacon"
let mysteryMeat = Food()// mysteryMeat's name is "[Unnamed]"
• Initializer 예
• 사용
Class Inheritance와 초기화
• Initializer 상속의예
class RecipeIngredient: Food {var quantity: Intinit(name: String, quantity: Int) {self.quantity = quantitysuper.init(name: name)
}override convenience init(name: String) {self.init(name: name, quantity: 1)
}}
Class Inheritance와 초기화
• Initializer 상속의예
class ShoppingListItem: RecipeIngredient {var purchased = falsevar description: String {var output = "\(quantity) x \(name)"output += purchased ? " ✔" : " ✘"return output
}}
Class Inheritance와 초기화
• Initializer 상속의예
var breakfastList = [ShoppingListItem(),ShoppingListItem(name: "Bacon"),ShoppingListItem(name: "Eggs", quantity: 6),
]breakfastList[0].name = "Orange juice"breakfastList[0].purchased = truefor item in breakfastList {print(item.description)
}// 1 x Orange juice ✔// 1 x Bacon ✘// 6 x Eggs ✘
Failable Initializer• ? : Failable Init() • 사용
struct Animal {let species: Stringinit?(species: String) {if species.isEmpty { return nil }self.species = species
}}
let someCreature = Animal(species: "Giraffe")
if let giraffe = someCreature {print("An animal was initialized with a species of \(giraffe.species)")
}
if someCreature == nil {print("The anonymous creature could not be initialized")
}
Failable Initializer for Enum• ? : Failable Init() for Enum
enum TemperatureUnit {case kelvin, celsius, fahrenheitinit?(symbol: Character) {switch symbol {case "K":self = .kelvin
case "C":self = .celsius
case "F":self = .fahrenheit
default:return nil
}}
} let fahrenheitUnit = TemperatureUnit(symbol: "F")if fahrenheitUnit != nil {print("This is a defined temperature unit, so initialization succeeded.")
}
let unknownUnit = TemperatureUnit(symbol: "X")if unknownUnit == nil {print("This is not a defined temperature unit, so initialization failed.")
}
Failable Initializer for Enum• ? : Failable Init() for Enum with Raw
enum TemperatureUnit: Character {case kelvin = "K", celsius = "C", fahrenheit = "F"
}
let fahrenheitUnit = TemperatureUnit(rawValue: "F")
if fahrenheitUnit != nil {print("This is a defined temperature unit, so initialization succeeded.")
}// Prints "This is a defined temperature unit, so initialization succeeded."
let unknownUnit = TemperatureUnit(rawValue: "X")
if unknownUnit == nil {print("This is not a defined temperature unit, so initialization failed.")
}// Prints "This is not a defined temperature unit, so initialization failed."
Failable Initializer 상속• Overriding
class Document {var name: String?// this initializer creates a document with a nil name valueinit() {}// this initializer creates a document with a nonempty name valueinit?(name: String) {if name.isEmpty { return nil }self.name = name
}}
class AutomaticallyNamedDocument: Document {override init() {super.init()self.name = "[Untitled]"
}override init(name: String) {super.init()if name.isEmpty {self.name = "[Untitled]"
} else {self.name = name
}}
}
Closure로 초기화
•형식
struct Chessboard {let boardColors: [Bool] = {var temporaryBoard = [Bool]()var isBlack = falsefor i in 1...8 {for j in 1...8 {temporaryBoard.append(isBlack)isBlack = !isBlack
}isBlack = !isBlack
}return temporaryBoard
}()func squareIsBlackAt(row: Int, column: Int) ‐> Bool {return boardColors[(row * 8) + column]
}}
Deinitialization•형식 • Bank/Player
deinit {// perform the deinitialization
}
class Bank {static var coinsInBank = 10_000static func distribute(coins numberOfCoinsRequested: Int) ‐> Int {let numberOfCoinsToVend = min(numberOfCoinsRequested, coinsInBank)coinsInBank ‐= numberOfCoinsToVendreturn numberOfCoinsToVend
}static func receive(coins: Int) {coinsInBank += coins
}}
Deinitialization• Bank/Player
• Player는종료되면가진 coin을반환 ‐> deinit
class Player {var coinsInPurse: Intinit(coins: Int) {coinsInPurse = Bank.distribute(coins: coins)
}func win(coins: Int) {coinsInPurse += Bank.distribute(coins: coins)
}deinit {Bank.receive(coins: coinsInPurse)
}}
Deinitialization• Bank/Player 사용
• win
• player 종료되며 coin 반환
var playerOne: Player? = Player(coins: 100)print("A new player has joined the game with \(playerOne!.coinsInPurse) coins")print("There are now \(Bank.coinsInBank) coins left in the bank")
playerOne!.win(coins: 2_000)print("PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse) coins")print("The bank now only has \(Bank.coinsInBank) coins left")
playerOne = nilprint("PlayerOne has left the game")print("The bank now has \(Bank.coinsInBank) coins")
Subscript• [ ] 를이용한컬렉션 접근
• 컬렉션, 리스트, 배열등의항목을 [ ] 형태로접근• [index] 형태사용을위해 subscript 정의필요
• index로 string도가능
• read‐only computed properties 인경우
subscript(index:Int) ‐> Int {get {// 항목에대한접근처리}set(newValue) {// newValue에대한처리}}
subscript(index:Int) ‐> Int {// 항목에대한접근처리
}
Subscript•예 : subscript 정의
•예 : subscript 사용
struct TimesTable {let multiplier: Intsubscript(index: Int) ‐> Int {return multiplier * index
}}
let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])")
// Prints "six times three is 18"
Subscript•예 : Matrix의 Subscript 구현
• Matrix 선언
• Matrix에데이터넣기
var matrix = Matrix(rows: 2, columns: 2)
matrix[0, 1] = 1.5matrix[1, 0] = 3.2
Subscript•예 : Matrix의 Subscript 구현
struct Matrix {let rows: Int, columns: Intvar grid: [Double]init(rows: Int, columns: Int) {self.rows = rowsself.columns = columnsgrid = Array(repeating: 0.0, count: rows * columns)
}func indexIsValid(row: Int, column: Int) ‐> Bool {return row >= 0 && row < rows && column >= 0 && column < columns
}subscript(row: Int, column: Int) ‐> Double {get {assert(indexIsValid(row: row, column: column), "Index out of range")return grid[(row * columns) + column]
}set {assert(indexIsValid(row: row, column: column), "Index out of range")grid[(row * columns) + column] = newValue
}}
}