develop

Standard Library Protocol 본문

iOS

Standard Library Protocol

pikachu987 2021. 1. 16. 15:44
반응형

equatable

equatable은 비교를 할수 있게 해주는 프로토콜이며기본적인 데이터 타입들도 적용이 되어있다.

extension String : Equatable {

    /// Returns a Boolean value indicating whether two values are equal.
    ///
    /// Equality is the inverse of inequality. For any values `a` and `b`,
    /// `a == b` implies that `a != b` is `false`.
    ///
    /// - Parameters:
    ///   - lhs: A value to compare.
    ///   - rhs: Another value to compare.
    public static func == (lhs: String, rhs: String) -> Bool
}

 

우리가 struct나 class 를 만들었을 때 비교를 하려면 Binary operator '==' cannot be applied to two '' operands 라는 컴파일 에러가 난다.

struct NumberInt {
    let value: Int
}

class NumberDouble {
    let value: Double

    init(value: Double) {
        self.value = value
    }
}

if NumberInt(value: 2) == NumberInt(value: 5) {

}

if NumberDouble(value: 3) == NumberDouble(value: 2) {

}

 

struct에 equatable 프로토콜을 추가하면

struct NumberInt: Equatable {
    let value: Int
}

if NumberInt(value: 2) == NumberInt(value: 5) {

}

 

하지만 class에 equtable 프로토콜을 추가하면

class NumberDouble: Equatable {
    let value: Double

    init(value: Double) {
        self.value = value
    }
}

if NumberDouble(value: 3) == NumberDouble(value: 2) {

}

 

Type 'NumberDouble' does not conform to protocol 'Equatable'

이란 컴파일 에러가 난다.== 메서드를 적어줘야 한다.

 

class NumberDouble: Equatable {
    static func == (lhs: NumberDouble, rhs: NumberDouble) -> Bool {
        return lhs.value == rhs.value
    }

    let value: Double

    init(value: Double) {
        self.value = value
    }
}

if NumberDouble(value: 3) == NumberDouble(value: 2) {

}

이렇게 == 메서드를 적어주면 컴파일 에러없이 잘 동작한다.

 

class NumberDouble: Equatable {
    let value: Double

    init(value: Double) {
        self.value = value
    }
}

func == (lhs: NumberDouble, rhs: NumberDouble) -> Bool {
    return lhs.value == rhs.value
}

이렇게 ==을 밖에서 구현해도 가능하다.

 

struct는 ==가 기본적으로 구현이 되어있고 내가 다시 구현해줄수 있다.

struct NumberInt: Equatable {
    let value: Int

    static func == (lhs: NumberInt, rhs: NumberInt) -> Bool {
        return lhs.value == rhs.value
    }
}

 

comparable

크고 작음을 비교하는 프로토콜이고 Equatable을 상속받아서 class에서는 Equatable에 있는 ==를 써주어야 한다.

struct NumberInt: Comparable {
    let value: Int

    static func < (lhs: NumberInt, rhs: NumberInt) -> Bool {
        return lhs.value < rhs.value
    }
}

class NumberDouble: Comparable {
    let value: Double

    init(value: Double) {
        self.value = value
    }

    static func == (lhs: NumberDouble, rhs: NumberDouble) -> Bool {
        return lhs.value == rhs.value
    }

    static func < (lhs: NumberDouble, rhs: NumberDouble) -> Bool {
        return lhs.value < rhs.value
    }
}

if NumberInt(value: 2) < NumberInt(value: 5) {

}

if NumberDouble(value: 3) > NumberDouble(value: 2) {

}

< 만 구현해 주어도 >나 >=, <=를 사용할 수 있다.

<와 ==을 구현해 주었으니까 나머지는 자동으로 계산이 된다.

 

sequence, iteratorProtocol

sequence는 한번에 하나씩 수행할수 있는 값의 목록이다.

sequence를 써주면 iteratorProtocol를 같이 써주어야 하는데

struct CountDown: Sequence, IteratorProtocol {
    var count: Int

    mutating func next() -> Int? {
        if count == 0 {
            return nil
        } else {
            defer { count -= 1 }
            return count
        }
    }
}

let countDown = CountDown(count: 5)
for i in countDown {
    print(i)
}

이렇게 사용가능하다.

CountDown 는 자체 iterator로 사용되는 sequence 정의이다.

아래 Sequence와 IteratorProtocol이 어떻게 만들어졌는지 보면 확실히 이해가 될것이다.

public protocol Sequence {

    /// A type representing the sequence's elements.
    associatedtype Element where Self.Element == Self.Iterator.Element, Self.Iterator.Element == Self.SubSequence.Element, Self.SubSequence.Element == Self.SubSequence.Iterator.Element

    /// A type that provides the sequence's iteration interface and
    /// encapsulates its iteration state.
    associatedtype Iterator : IteratorProtocol

    /// A type that represents a subsequence of some of the sequence's elements.
    associatedtype SubSequence : Sequence = AnySequence<Self.Element> where Self.SubSequence == Self.SubSequence.SubSequence

    /// Returns an iterator over the elements of this sequence.
    public func makeIterator() -> Self.Iterator
}

public protocol IteratorProtocol {

    /// The type of element traversed by the iterator.
    associatedtype Element

    /// Advances to the next element and returns it, or `nil` if no next element
    /// exists.
    ///
    /// Repeatedly calling this method returns, in order, all the elements of the
    /// underlying sequence. As soon as the sequence has run out of elements, all
    /// subsequent calls return `nil`.
    ///
    /// You must not call this method if any other copy of this iterator has been
    /// advanced with a call to its `next()` method.
    ///
    /// The following example shows how an iterator can be used explicitly to
    /// emulate a `for`-`in` loop. First, retrieve a sequence's iterator, and
    /// then call the iterator's `next()` method until it returns `nil`.
    ///
    ///     let numbers = [2, 3, 5, 7]
    ///     var numbersIterator = numbers.makeIterator()
    ///
    ///     while let num = numbersIterator.next() {
    ///         print(num)
    ///     }
    ///     // Prints "2"
    ///     // Prints "3"
    ///     // Prints "5"
    ///     // Prints "7"
    ///
    /// - Returns: The next element in the underlying sequence, if a next element
    ///   exists; otherwise, `nil`.
    public mutating func next() -> Self.Element?
}

 

customStringConvertible

오브젝트를 문자열로 바꾸는 기능을 제공하는 프로토콜이다.

struct CustomStruct: CustomStringConvertible {
    let value: String
    var description: String {
        return "CustomStruct value: \(value)"
    }
}

class CustomClass: CustomStringConvertible {
    var value: String
    var description: String {
        return "CustomClass value: \(value)"
    }
    init(value: String) {
        self.value = value
    }
}

print(CustomStruct(value: "Hello").description)
print(CustomClass(value: "Hello").description)

class는 CustomStringConvertible을 추가하지 않아도 description를 사용할수 있다.

하지만 CustomStringConvertible를 추가하면 description를 구현해주어야 한다.

 

 

 

 

이 외에도 많은 표준 라이브러리 프로토콜이 있다.

https://developer.apple.com/documentation/swift/swift_standard_library

 

Apple Developer Documentation

 

developer.apple.com

 

반응형

'iOS' 카테고리의 다른 글

DispatchGroup  (0) 2021.01.18
final Keyword  (0) 2021.01.17
OptionSet  (0) 2021.01.15
AccessControl 접근 한정자  (0) 2021.01.14
where Keyword (for의 where, switch 의 where, extension의 where, func의 where)  (0) 2021.01.13
Comments