protocol SomeProtocol: Hashable, Codable { // λ€λ₯Έ νλ‘ν μ½ μ±ν κ°λ₯.
// μꡬμ¬ν μ μ
}
class SomeClass: SomeSuperClass, Hashable, Codable {
// μμμ΄ λ¨Όμ , νλ‘ν μ½ μ±νμ΄ λμ€μ.
}
protocol SomeProtocol {
var mustBeSettable: Int { get set } // 무쑰건 set μ΄ κ°λ₯ν΄μΌν¨.
var doesNotNeedToBeSettable: Int { get } // set μ κ°λ₯ν μλ? μλμλ?
static var someTypeProperty: Int { get set }
}
λ€λ₯Έ λ³μλ₯Ό λ ꡬννλ κ²μ μκ΄ μμΌλ, νλ‘ν μ½μ μꡬλλ λ³μλ λͺ¨λ ꡬνν΄μΌνλ€.
protocol SomeProtocol {
static func someTypeMethod()
}
protocol RandomNumberGenerator {
func random() -> Double
}
class LinearCongruentialGenerator: RandomNumberGenerator {
var lastRandom = 42.0
let m = 139968.0
let a = 3877.0
let c = 29573.0
func random() -> Double {
lastRandom = ((lastRandom * a + c)
.truncatingRemainder(dividingBy:m))
return lastRandom / m
}
}
let generator = LinearCongruentialGenerator()
print("Here's a random number: \(generator.random())")
print("And another one: \(generator.random())")
mutating
ν€μλλ₯Ό μ¬μ©.protocol Togglable {
mutating func toggle()
}
enum OnOffSwitch: Togglable {
case off, on
mutating func toggle() {
switch self {
case .off:
self = .on
case .on:
self = .off
}
}
}
var lightSwitch = OnOffSwitch.off
lightSwitch.toggle() // .on
protocol SomeProtocol {
init(someParameter: Int)
}
required
ν€μλλ₯Ό λΆμ¬μ€μΌ νλ€.class SomeClass: SomeProtocol {
required init(someParameter: Int) {
// initializer implementation goes here
}
}
required override init
μΌλ‘ κ°μ΄ μ°λ©΄ λλ€.protocol SomeProtocol {
init()
}
class SomeSuperClass {
init() {
// initializer implementation goes here
}
}
class SomeSubClass: SomeSuperClass, SomeProtocol {
// "required" from SomeProtocol conformance; "override" from SomeSuperClass
required override init() {
// initializer implementation goes here
}
}
init
μΌλ‘ ꡬνν΄λ, init?
μΌλ‘ ꡬνν΄λ μ¬μ©ν μ μλ€.ν΄λΉ νλ‘ν μ½μ μ€μνλ μ΄λ€ νμ
μ΄λΌλ λ».class Dice {
let sides: Int
let generator: RandomNumberGenerator
// generator κ° RandomNumberGenerator λΌλ νμ
μ μ±ννλ μ΄λ€ νμ
μ μΈμ€ν΄μ€μ.
// λ€μ΄ μΊμ€ν
μΌλ‘ κΈ°μ‘΄ νμ
μΌλ‘ μ¬μ© κ°λ₯.
init(sides: Int, generator: RandomNumberGenerator)
self.sides = sides
self.generator = generator
}
func roll() -> Int {
return Int(generator.random() * Double(sides)) + 1
}
}
var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())
for _ in 1...5 {
print("Random dice roll is \(d6.roll())")
}
protocol DiceGame { // κ²μμ μ±νλλ νλ‘ν μ½
var dice: Dice { get }
func play()
}
protocol DiceGameDelegate: AnyObject { // κ²μ μ§ν μν©μ μΆμ νλλ° μ±ν
func gameDidStart(_ game: DiceGame)
func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int)
func gameDidEnd(_ game: DiceGame)
}
weak
λ‘ μ μΈ.class SnakesAndLadders: DiceGame {
let finalSquare = 25
let dice = Dice(sides: 6, generator: LinearCongruentialGenerator())
var square = 0
var board: [Int]
init() {
board = Array(repeating: 0, count: finalSquare + 1)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
}
weak var delegate: DiceGameDelegate?
func play() {
square = 0
delegate?.gameDidStart(self)
gameLoop: while square != finalSquare {
let diceRoll = dice.roll()
delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
switch square + diceRoll {
case finalSquare:
break gameLoop
case let newSquare where newSquare > finalSquare:
continue gameLoop
default:
square += diceRoll
square += board[square]
}
}
delegate?.gameDidEnd(self)
}
}
class DiceGameTracker: DiceGameDelegate {
var numberOfTurns = 0
func gameDidStart(_ game: DiceGame) {
numberOfTurns = 0
if game is SnakesAndLadders {
print("Started a new game of Snakes and Ladders")
}
print("The game is using a \(game.dice.sides)-sided dice")
}
func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) {
numberOfTurns += 1
print("Rolled a \(diceRoll)")
}
func gameDidEnd(_ game: DiceGame) {
print("The game lasted for \(numberOfTurns) turns")
}
}
let tracker = DiceGameTracker()
let game = SnakesAndLadders()
game.delegate = tracker
game.play()
extension
μΌλ‘ νλ‘ν μ½μ μ€μνκ² ν μ μλ€.protocol TextRepresentable {
var textualDescription: String { get }
}
extension Dice: TextRepresentable {
var textualDescription: String {
return "A \(sides)-sided dice"
}
}
let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator())
print(d12.textualDescription) // Prints "A 12-sided dice"
// λ°°μ΄μ μμκ° TextRespresentable μ λ°λ₯Ό λ Array λ TextRepresentable.
extension Array: TextRepresentable where Element: TextRepresentable {
var textualDescription: String {
let itemsAsText = self.map { $0.textualDescription }
return "[" + itemsAsText.joined(separator: ", ") + "]"
}
}
let myDice = [d6, d12]
print(myDice.textualDescription) // Prints "[A 6-sided dice, A 12-sided dice]"
struct Hamster {
var name: String
var textualDescription: String {
return "A hamster named \(name)"
}
}
extension Hamster: TextRepresentable {}
Equatable
, Hashable
, Comparable
νλ‘ν μ½ μ€μμ±μ μλμΌλ‘ μ 곡νλ€.Equatable
μ == !=
μ μ¬μ©νκΈ° μν΄ λ§€λ² μ°μ°μλ₯Ό ꡬνν΄μΌνλ κ²μ΄ μλλ€.struct Vector3D: Equatable {
var x = 0.0, y = 0.0, z = 0.0
}
let twoThreeFour = Vector3D(x: 2.0, y: 3.0, z: 4.0)
let anotherTwoThreeFour = Vector3D(x: 2.0, y: 3.0, z: 4.0)
if twoThreeFour == anotherTwoThreeFour {
print("These two vectors are also equivalent.")
}
hash(into:)
λΌλ ν¨μλ₯Ό λ§€λ² κ΅¬νν νμκ° μμ.https://developer.apple.com/documentation/swift/hashable#2849490
< > >= <=
λ₯Ό κΈ°λ³Έ μ 곡.enum SkillLevel: Comparable {
case beginner
case intermediate
case expert(stars: Int)
}
var levels = [SkillLevel.intermediate, SkillLevel.beginner,
SkillLevel.expert(stars: 5), SkillLevel.expert(stars: 3)]
for level in levels.sorted() {
print(level)
}
// Prints "beginner"
// Prints "intermediate"
// Prints "expert(stars: 3)"
// Prints "expert(stars: 5)"
let things: [TextRepresentable] = [game, d12, simonTheHamster]
for thing in things {
print(thing.textualDescription)
}
// A game of Snakes and Ladders with 25 squares
// A 12-sided dice
// A hamster named Simon
protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
// protocol definition goes here
}
protocol PrettyTextRepresentable: TextRepresentable {
var prettyTextualDescription: String { get }
}
// κΈ°μ‘΄μ TextRepresentable μ μ€μνκ³ μλ SnakesAndLadders μμ
// PrettyTextRepresentable μ μ±ν
extension SnakesAndLadders: PrettyTextRepresentable {
var prettyTextualDescription: String {
// μ΄λ―Έ TextRepresentable μ΄λ―λ‘ textualDescription νλ‘νΌν°μ μ κ·Ό κ°λ₯.
var output = textualDescription + ":\n"
for index in 1...finalSquare {
switch board[index] {
case let ladder where ladder > 0:
output += "β² "
case let snake where snake < 0:
output += "βΌ "
default:
output += "β "
}
}
return output
}
}
AnyObject
λ₯Ό μΆκ°νλ©΄ ν΄λμ€μμλ§ κ΅¬νν μ μκ² λ§λ€ μ μλ€.protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
// class-only protocol definition goes here
}
Equtable & Comparable
protocol Named {
var name: String { get }
}
protocol Aged {
var age: Int { get }
}
struct Person: Named, Aged {
var name: String
var age: Int
}
// Person λμ Named & Aged λ₯Ό μ¬μ©.
// Person μ΄ μλ λ νλ‘ν μ½μ ꡬνν μ΄λ€ κ²μ΄λΌλ μΈμκ° λ μ μμ.
func wishHappyBirthday(to celebrator: Named & Aged) {
print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!")
}
let birthdayPerson = Person(name: "Malcolm", age: 21)
wishHappyBirthday(to: birthdayPerson)
// Prints "Happy birthday, Malcolm, you're 21!"
is
as
μ¬μ©.is
: νλ‘ν μ½μ μ€μνλ©΄ true μλλ©΄ falseas? as!
: λ€μ΄ μΊμ€ν
.optional
μμμ΄λ₯Ό λΆμ.@objc
λΆμ¬μΌν¨.// μ€μ μ½λμμ optional λ§ μλ μ½λλ λ³λ‘ μ’μ§ μμ.
@objc protocol CounterDataSource {
@objc optional func increment(forCount count: Int) -> Int
@objc optional var fixedIncrement: Int { get }
}
class Counter {
var count = 0
var dataSource: CounterDataSource?
func increment() { // count μ¦κ°.
// increment κ° optional func μ΄κΈ° λλ¬Έμ ? μ λΆμ¬ 체μ΄λ.
// μ€μ ꡬνλΆμ μλ ν¨μλ₯Ό μ€ννλ κ².
if let amount = dataSource?.increment?(forCount: count) {
count += amount
} else if let amount = dataSource?.fixedIncrement {
count += amount
}
}
}
// ContuerDataSource λ₯Ό μ€μ λ‘ κ΅¬ννλ λΆλΆ.
class ThreeSource: NSObject, CounterDataSource {
let fixedIncrement = 3
}
var counter = Counter()
counter.dataSource = ThreeSource()
for _ in 1...4 {
counter.increment()
print(counter.count) // 3 6 9 12
}
// μ§μ μ΄λμ κ° νλ‘ν μ½μ μ€μνλ € ꡬνμ νμ§ μμλ νλ‘ν μ½λ§ μ±ννλ©΄ μ¬μ© κ°λ₯.
extension RandomNumberGenerator {
func randomBool() -> Bool {
return random() > 0.5
}
}
extension PrettyTextRepresentable {
var prettyTextualDescription: String {
return textualDescription
}
}
extension Collection where Element: Equatable {
func allEqual() -> Bool {
for element in self {
if element != self.first { // != μ¬μ©νλ €κ³ Equatable 쑰건 건 κ².
return false
}
}
return true
}
}
let equalNumbers = [100, 100, 100, 100, 100]
let differentNumbers = [100, 100, 200, 100, 200]
print(equalNumbers.allEqual()) // true
print(differentNumbers.allEqual()) // false
hash(into: )
λ₯Ό μ§μ ꡬνν custom typeλΈλ¦¬κ²μ΄νΈλ μμ λ°©μμ΄λ€.
λ Έν°νΌμΌμ΄μ μ
μ°¨μ΄μ μ,
λΈλ¦¬κ²μ΄νΈλ νλ‘ν μ½μ μ΄μ©ν΄μ νκΈ° λλ¬Έμ μ격ν κ·μΉμ μ§μΌμΌνλ€.
νλ‘ν μ½μ ꡬνν νλμ VC μμμ λ³΄ν΅ μ²λ¦¬κ° λλ€.
delegate μμ μ΄λ²€νΈλ₯Ό λ°μμν€λ©΄, μ΄λ²€νΈκ° λ°μνμ λ μ§μ μ μΌλ‘ delegate λ΄μ ν¨μλ₯Ό νΈμΆν΄μ μ²λ¦¬λ₯Ό νκΈ° λλ¬Έμ λ‘μ§μ νλ¦μ λ°λΌκ°κΈ° μ½λ€.
λ Έν°νΌμΌμ΄μ μ μ΄λ²€νΈλ₯Ό post λ‘ λ°μμν€κ³ observer λ‘ κ·Έ μ΄λ²€νΈλ₯Ό μ‘κΈ° λλ¬Έμ μ½κ² ꡬνμ΄ κ°λ₯νμ§λ§,
μ΄λ€ κ³³μμ λ°μν΄μ ν¨μκ° μ€νλ건μ§μ λν μΆμ μ΄ μ½μ§ μμ μ μμ΅λλ€.
λ λ€ λ€νμ±μ ꡬννκΈ° μν λ°©λ²μ΄λ€.
νλ‘ν μ½ μ§ν₯ νλ‘κ·Έλλ°
μμ±
μ κ°μ§κ³ μλ€λΌλ has-A μλ―Έ ꡬ쑰λ₯Ό ννν μ μμ.κ°μ²΄ μ§ν₯ νλ‘κ·Έλλ°
μ°Έκ³
https://bbiguduk.gitbook.io/swift/language-guide-1/protocols
https://velog.io/@hayeon/Hashableμ΄-무μμ΄κ³ -Equatableμ-μ-μμν΄μΌ-νλμ§-μ€λͺ
νμμ€