2017-02-21 16 views
1

Я работаю над книгой о Swift, и я понимаю идею сферы в функциях, поэтому то, что я хотел бы понять далее, - это то, почему мы устанавливаем глобальные переменные, используя необязательные типы в классах. Честно говоря, похоже, что мы не устанавливаем эти переменные для одного слова, а просто даем классу знать, что в кодовой базе будет какая-то переменная определенного типа: var sut: ItemManager!.Понимание необязательных глобальных переменных в swift

Из того, что я понимаю, переменная sut является развернутой опцией типа ItemManger, которая определенно имеет допустимое значение, а не ноль. Причина, по которой мы установили его с восклицательным знаком или вопросительным знаком, состоит в том, что в этом классе нет инициализатора. Что непонятно, так как этот класс не имеет инициализатора, какие факторы вступают в игру, когда вы определяете погоду, чтобы установить эту глобальную переменную на необязательную, используя знак вопроса или неявно развернутую с восклицательным знаком?

import XCTest 
    @testable import ToDo 

    class ItemManagerTests: XCTestCase { 

     var sut: ItemManager! 

     override func setUp() { 
      super.setUp() 
      // Put setup code here. This method is called before the invocation of each test method in the class. 

      sut = ItemManager.init() 
     } 

     override func tearDown() { 
      // Put teardown code here. This method is called after the invocation of each test method in the class. 
      super.tearDown() 
     } 


     func test_ToDoCount_InitiallySetAtZero(){ 

      let sut = ItemManager.init() 

      XCTAssertEqual(sut.toDoCount, 0) 
     } 

     func test_DoneCount_InitiallySetAtZero(){ 

      let sut = ItemManager.init() 

      XCTAssertEqual(sut.doneCount, 0) 
     } 
    } 

ответ

0

Причина мы установили его с восклицательным знаком или знаком вопроса является , потому что не инициализатор в этом классе

Потому что, когда каждый экземпляр класса инициализируется, то есть для выделения памяти для своих свойств/экземпляра var. Таким образом, с var sut: ItemManager!, значение sut составляет nil, когда init. Без !, ? компилятор не может выделить init, поэтому вам нужно инициализировать вручную в инициализаторе. Вот что сказал вам компилятор.

Для использования ! или ?.

  • ! используется, когда свойство/var всегда имеет значение после первого присвоения. И после того, как в первый раз он назначен, он не может быть нулевым позже
  • ? используется, когда про/вар может иметь значение или нет
+1

Ни одна из претензий в первом элементе в вашем списке не верна. Для IUO отлично не иметь ценности - просто убедитесь, что вы не обращаетесь к ним без него. – Andreas

3

sut не является глобальной переменной.

sut является переменной экземпляра of ItemManagerTests. Каждый раз, когда создается экземпляр нового объекта, то есть объект, из ItemManagerTests, память выделяется для sut.

Это тип ItemManager!. Это неявно разворачивается необязательно. Он похож на ItemManager? (a.k.a. Необязательно), с тем отличием, что он неявно принудительно разворачивается везде, где он используется напрямую, как если бы использовался оператор разворота силы (!).

Его значение инициализируется значением nil, но устанавливается на новый объект ItemManager, когда setUp вызывается инфраструктурой тестирования Xcode.

3

Во-первых, sut не является глобальным. Глобальная переменная в Swift объявляется вне любой охватывающей области (Итак, перед оператором class). sut - свойство экземпляра; каждый экземпляр вашего класса ItemManagerTests будет иметь свойство sut.

В Swift все необязательные свойства должны быть инициализированы к моменту завершения инициализатора.В некоторых случаях это может быть достигнуто с помощью кода внутри инициализатора и в других случаях путем назначения значения по умолчанию.

В некоторых случаях вы не можете назначить или не хотите назначать значение по умолчанию, и вы не можете (или не хотите) переопределять инициализатор.

Если вы использовали обычный факультативный код, то компилятор будет удовлетворен тем, что свойство не было инициализировано по умолчанию или в инициализаторе, но каждый раз, когда вы ссылались на свойство, вам пришлось бы его разворачивать (например, sut?.donecount).

Поскольку тестовый случай присвоение значения sut в setup, вы знаете, что это будет иметь значение, и вы могли бы использовать силы развертку (например sut!.donecount), или, еще один шаг дальше и использовать неявно развернутый по желанию , Это позволяет вам ссылаться на свойство без какой-либо разворачивания, но оно по-прежнему является необязательным и будет по-прежнему вызывать сбои, если оно равно nil.

Обратите внимание, что ваш текущий код даже не использует это свойство, так как вы распределяете локальную переменную в своих тестовых случаях. Вы можете использовать:

class ItemManagerTests: XCTestCase { 

    var sut: ItemManager! 

    override func setUp() { 
     super.setUp() 
     // Put setup code here. This method is called before the invocation of each test method in the class. 

     sut = ItemManager.init() 
    } 

    override func tearDown() { 
     // Put teardown code here. This method is called after the invocation of each test method in the class. 
     super.tearDown() 
    } 

    func test_ToDoCount_InitiallySetAtZero() { 

     XCTAssertEqual(sut.toDoCount, 0) 
    } 

    func test_DoneCount_InitiallySetAtZero() { 

     XCTAssertEqual(sut.doneCount, 0) 
    } 
}