Swift Protocols


Extensions add new functionality to an existing class, structure, enumeration, or protocol type. This includes the ability to extend types for which you do not have access to the original source code (known as retroactive modeling). 

Extensions in Swift can:

  • Add computed instance properties and computed type properties (stored property는 추가 할수 없다.)
  • Define instance methods and type methods
  • Provide new initializers
  • Define subscripts
  • Define and use new nested types
  • Make an existing type conform to a protocol

In Swift, you can even extend a protocol to provide implementations of its requirements or add additional functionality that conforming types can take advantage of. For more details, see Protocol Extensions.


Extensions can add new functionality to a type, but they cannot override existing functionality.

Extension Syntax

Declare extensions with the extension keyword:

extension SomeType {
   // new functionality to add to SomeType goes here

An extension can extend an existing type to make it adopt one or more protocols. To add protocol conformance, you write the protocol names the same way as you write them for a class or structure:

extension SomeType: SomeProtocol, AnotherProtocol {
   // implementation of protocol requirements goes here

Adding protocol conformance in this way is described in Adding Protocol Conformance with an Extension.

An extension can be used to extend an existing generic type, as described in Extending a Generic Type. You can also extend a generic type to conditionally add functionality, as described in Extensions with a Generic Where Clause.


If you define an extension to add new functionality to an existing type, the new functionality will be available on all existing instances of that type, even if they were created before the extension was defined

Computed Properties

Extensions can add computed instance properties and computed type properties to existing types. This example adds five computed instance properties to Swift’s built-in Double type, to provide basic support for working with distance units:

extension Double {
   var km: Double { return self * 1_000.0 }
   var m: Double { return self }
   var cm: Double { return self / 100.0 }
   var mm: Double { return self / 1_000.0 }
   var ft: Double { return self / 3.28084 }
let oneInch = 25.4.mm
print(“One inch is (oneInch) meters”)
// Prints “One inch is 0.0254 meters”
let threeFeet = 3.ft
print(“Three feet is (threeFeet) meters”)
// Prints “Three feet is 0.914399970739201 meters”

let aMarathon = 42.km + 195.m
print(“A marathon is (aMarathon) meters long”)
// Prints “A marathon is 42195.0 meters long”


Extensions can add new computed properties, but they cannot add stored properties, or add property observers to existing properties.


Extensions can add new initializers to existing types. 

Extensions can add new convenience initializers to a class, but they cannot add new designated initializers or deinitializers to a class. Designated initializers and deinitializers must always be provided by the original class implementation.


If you use an extension to add an initializer to a value type that provides default values for all of its stored properties and does not define any custom initializers, you can call the default initializer and memberwise initializer for that value type from within your extension’s initializer.

This would not be the case if you had written the initializer as part of the value type’s original implementation, as described in Initializer Delegation for Value Types.

struct Size {
   var width = 0.0, height = 0.0
struct Point {
   var x = 0.0, y = 0.0
struct Rect {
   var origin = Point()
   var size = Size()

let defaultRect = Rect()
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),
                         size: Size(width: 5.0, height: 5.0))

You can extend the Rect structure to provide an additional initializer that takes a specific center point and size:

extension Rect {
   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)

This new initializer starts by calculating an appropriate origin point based on the provided center point and size value. The initializer then calls the structure’s automatic memberwise initializer init(origin:size:), which stores the new origin and size values in the appropriate properties:

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)


Extensions can add new instance methods and type methods to existing types. The following example adds a new instance method called repetitions to the Int type:

extension Int {
   func repetitions(task: () -> Void) {

      // 0과 self사이의 정수를 인덱스로 순환

      // 참고) https://stackoverflow.com/a/26083896

       for _ in 0..<self {

3.repetitions {
// Hello!
// Hello!
// Hello!

Mutating Instance Methods

(참고사항 tumblr #swift #mutating #enum: 

Structures and enumerations are value types. By default, the properties of a value type cannot be modified from within its instance methods.)

Instance methods added with an extension can also modify (or mutate) the instance itself. Structure and enumeration methods that modify self or its properties must mark the instance method as mutating, just like mutating methods from an original implementation.

extension Int {
   mutating func square() {
       self = self * self
var someInt = 3
// someInt is now 9


Extensions can add new subscripts to an existing type. 

123456789[0] returns 9

123456789[1] returns 8

extension Int {
   subscript(digitIndex: Int) -> Int {
       var decimalBase = 1
       for _ in 0..<digitIndex {
           decimalBase *= 10
       return (self / decimalBase) % 10
// returns 5
// returns 9
// returns 2
// returns 7

// returns 0, as if you had requested:

Nested Types

Extensions can add new nested types to existing classes, structures, and enumerations:

extension Int {
   enum Kind {
       case negative, zero, positive
   var kind: Kind {
       switch self {
       case 0:
           return .zero
       case let x where x > 0:
           return .positive
           return .negative

func printIntegerKinds(_ numbers: [Int]) {
   for number in numbers {
       switch number.kind {
       case .negative:
           print(“- ”, terminator: “”)
       case .zero:
           print(“0 ”, terminator: “”)
       case .positive:
           print(“+ ”, terminator: “”)
printIntegerKinds([3, 19, -27, 0, -6, 0, 7])
// Prints “+ + – 0 – 0 + ”


number.kind is already known to be of type Int.Kind. Because of this, all of the Int.Kind case values can be written in shorthand form inside the switch statement, such as .negative rather than Int.Kind.negative

Static vs class functions/variables in Swift classes?


Methods are functions that are associated with a particular type. Classes, structures, and enumerations can all define instance methods, which encapsulate specific tasks and functionality for working with an instance of a given type. Classes, structures, and enumerations can also define type methods, which are associated with the type itself.

Instance Methods

Instance methods are functions that belong to instances of a particular class, structure, or enumeration. They support the functionality of those instances, either by providing ways to access and modify instance properties, or by providing functionality related to the instance’s purpose. Instance methods have exactly the same syntax as functions, as described in Functions.

You write an instance method within the opening and closing braces of the type it belongs to. An instance method has implicit access to all other instance methods and properties of that type. An instance method can be called only on a specific instance of the type it belongs to. It cannot be called in isolation without an existing instance.

Here’s an example that defines a simple Counter class, which can be used to count the number of times an action occurs:

class Counter {
   var count = 0
   func increment() {
       count += 1

//  “amount” is parameter name
   func increment(by amount: Int) {
       count += amount
   func reset() {
       count = 0

The Counter class defines three instance methods:

let counter = Counter()
// the initial counter value is 0
// the counter’s value is now 1

// by is argument label
counter.increment(by: 5)
// the counter’s value is now 6
// the counter’s value is now 0

The self Property

Every instance of a type has an implicit property called self, which is exactly equivalent to the instance itself. You use the self property to refer to the current instance within its own instance methods.

The increment() method in the example above could have been written like this:

func increment() {
   self.count += 1

In practice, you don’t need to write self in your code very often. If you don’t explicitly write self, Swift assumes that you are referring to a property or method of the current instance whenever you use a known property or method name within a method. This assumption is demonstrated by the use of count (rather than self.count) inside the three instance methods for Counter.

The main exception to this rule occurs when a parameter name for an instance method has the same name as a property of that instance. In this situation, the parameter name takes precedence, and it becomes necessary to refer to the property in a more qualified way. You use the self property to distinguish between the parameter name and the property name.

Here, self disambiguates between a method parameter called x and an instance property that is also called x:

struct Point {
   var x = 0.0, y = 0.0
   func isToTheRightOf(x: Double) -> Bool {
       return self.x > x
let somePoint = Point(x: 4.0, y: 5.0)
if somePoint.isToTheRightOf(x: 1.0) {
   print(“This point is to the right of the line where x == 1.0”)
// Prints “This point is to the right of the line where x == 1.0”

(참고 https://medium.com/@andrea.prearo/reference-and-value-types-in-swift-dad40ea76226)

(참고 tumblr #swift  #var  #let  #reference  #value  #type  #mutable  #immutable  #immutablity  #variable )

Modifying Value Types from Within Instance Methods

Structures and enumerations are value types. By default, the properties of a value type cannot be modified from within its instance methods.

However, if you need to modify the properties of your structure or enumeration within a particular method, you can opt in to mutating behavior for that method. The method can then mutate (that is, change) its properties from within the method, and any changes that it makes are written back to the original structure when the method ends. The method can also assign a completely new instance to its implicit self property, and this new instance will replace the existing one when the method ends.

You can opt in to this behavior by placing the mutating keyword before the func keyword for that method:

struct Point {
   var x = 0.0, y = 0.0
   mutating func moveBy(x deltaX: Double, y deltaY: Double) {
       x += deltaX
       y += deltaY
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveBy(x: 2.0, y: 3.0)
print(“The point is now at ((somePoint.x), (somePoint.y))”)
// Prints “The point is now at (3.0, 4.0)”

Note that you cannot call a mutating method on a constant of structure type, because its properties cannot be changed, even if they are variable properties, as described in Stored Properties of Constant Structure Instances:

let fixedPoint = Point(x: 3.0, y: 3.0)
fixedPoint.moveBy(x: 2.0, y: 3.0)
// this will report an error

Assigning to self Within a Mutating Method

Mutating methods can assign an entirely new instance to the implicit self property. The Point example shown above could have been written in the following way instead:

struct Point {
   var x = 0.0, y = 0.0
   mutating func moveBy(x deltaX: Double, y deltaY: Double) {
       self = Point(x: x + deltaX, y: y + deltaY)

Mutating methods for enumerations can set the implicit self parameter to be a different case from the same enumeration:

enum TriStateSwitch {
   case off, low, high
   mutating func next() {
       switch self {
       case .off:
           self = .low
       case .low:
           self = .high
       case .high:
           self = .off
var ovenLight = TriStateSwitch.low
// ovenLight is now equal to .high
// ovenLight is now equal to .off

Type Methods

You can also define methods that are called on the type itself. These kinds of methods are called type methods. You indicate type methods by writing the static keyword before the method’s func keyword. Classes may also use the class keyword to allow subclasses to override the superclass’s implementation of that method. (static 을 사용하여 type method를 만드는데 단 class의 경우 subclass에서 override를 해야 하는 경우 static대신 class를 사용한다는 설명)


In Swift, you can define type-level methods for all classes, structures, and enumerations. Each type method is explicitly scoped to the type it supports.

Type methods are called with dot syntax, like instance methods. However, you call type methods on the type, not on an instance of that type. Here’s how you call a type method on a class called SomeClass(클래스이름에 dot notation을 사용한다는 뜻):

class SomeClass {
   class func someTypeMethod() {
       // type method implementation goes here

Within the body of a type method, the implicit self property refers to the type itself, rather than an instance of that type. This means that you can use self to disambiguate between type properties and type method parameters, just as you do for instance properties and instance method parameters.

More generally, any unqualified method and property names that you use within the body of a type method will refer to other type-level methods and properties. A type method can call another type method with the other method’s name, without needing to prefix it with the type name. Similarly, type methods on structures and enumerations can access type properties by using the type property’s name without a type name prefix.

(일반적으로는 self를 앞에 붙이지 않고 같은 type내의 method, property에 접근 가능하다는 이야기)

성취된 level을 type내에서 공유하면서도 각개인의 level을 유지관리하는 코드 예시

struct LevelTracker {
   static var highestUnlockedLevel = 1
   var currentLevel = 1
   static func unlock(_ level: Int) {
       if level > highestUnlockedLevel { highestUnlockedLevel = level }
   static func isUnlocked(_ level: Int) -> Bool {
       return level <= highestUnlockedLevel
   mutating func advance(to level: Int) -> Bool {
       if LevelTracker.isUnlocked(level) {
           currentLevel = level
           return true
       } else {
           return false

class Player {
   var tracker = LevelTracker()
   let playerName: String
   func complete(level: Int) {
       LevelTracker.unlock(level + 1)
       tracker.advance(to: level + 1)
   init(name: String) {
       playerName = name

var player = Player(name: “Argyrios”)
player.complete(level: 1)
print(“highest unlocked level is now (LevelTracker.highestUnlockedLevel)”)
// Prints “highest unlocked level is now 2”

player = Player(name: “Beto”)
if player.tracker.advance(to: 6) {
   print(“player is now on level 6”)
} else {
   print(“level 6 has not yet been unlocked”)
// Prints “level 6 has not yet been unlocked”

Java Generic Methods

Java Generics

A Guide to Python’s Magic Methods « rafekettler.com