Урок 2.3 Функции

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

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


Что Вы Узнаете

  • Как написать свои собственные функции, с возвращаемым типом или без него
  • Как указать входные параметры для ваших функций
  • Как вернуть несколько значений, когда это необходимо
  • Как настроить способ вызова ваших функций
  • Как предоставить функции значения параметров по умолчанию

Словарь


Связанные Ресурсы

Руководство по языку программирования Swift: Функции

Когда кто-то дает вам задание ”одеться", это кажется такой простой инструкцией. Но детали того, что вы будете носить, как вы будете надевать одежду и где вы будете брать одежду, заключены во фразе “одевайся”. Идея взять что-то сложное и определить более простой способ обращения к нему - это абстракция, а функция - один из основных способов создания абстракции в коде.

Функция состоит из имени, набора входных данных и набора выходных данных. Оба входа и выхода являются необязательными. Вы вызываете или обращаетесь к функцииы, чтобы заставить вашу программу выполнить что-то, например, вывести текст на консоль.

Представьте, что вы хотите отправить текстовое сообщение своему другу. “Отправить текстовое сообщение” - это то, что вы хотите сделать. Параметры - это контактная информация вашего друга и сообщение, которое вы хотите ему отправить. Возвращаемое значение - это то, получили ли они сообщение.

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

Подобно объявлению константы с помощью let или переменной с помощью var, ключевое слово func сообщает компилятору Swift, что вы объявляете функцию. Сразу после func вы добавляете имя функции, за которым следуют круглые скобки (), которые могут включать или не включать список параметров внутри них. Если функция имеет возвращаемое значение, вы напишете стрелку (->), за которой следует тип данных, которые будет возвращать функция, например Int, String, Person и так далее.

Определение функции

 

func functionName (parameters) -> ReturnType {
  // body of the function 
}

 

Вот пример функции, которая будет отображать первые десять цифр числа пи (π). Поскольку печать pi не требует дополнительного ввода, никаких параметров нет. И поскольку при печати pi не нужно возвращать ничего, относящегося к вызывающей функции, возвращаемое значение не указывается.

 

func displayPi() {
  print(”3.1415926535”)
}

 

Как только функция была правильно объявлена, вы можете вызвать ее или выполнить из любого места, просто написав ее имя.

 

displayPi()


Console Output:

3.1415926535

 

Параметры

Чтобы указать функцию с параметром, вставьте имя значения, двоеточие (:) и тип значения — все в круглых скобках. Например, предположим, что вы хотели написать функцию с именем triple, которая принимает значение Int, утраивает значение, а затем выводит его.

func triple(value: Int) {
  let result = value * 3
  print(”If you multiply \(value) by 3, you’ll get \(result).”)
}

В приведенном выше случае параметр value является константой, которую вы можете использовать внутри функции. Когда вы вызываете функцию, вы передаете значения для ее параметров в качестве аргументов. В приведенном ниже коде аргумент для value в вызове функции triple(value:) равен 10.

 

triple(value: 10)


Console Output:
If you multiply 10 by 3, you’ll get 30.

 

Чтобы присвоить функции несколько параметров, разделите каждый параметр запятой (,). Вот пример функции, которая принимает два параметра Int, умножает их вместе, а затем выводит результат:

 

func multiply(firstNumber: Int, secondNumber: Int) {
  let result = firstNumber * secondNumber
  print(”The result is \(result).”)
}

 

Затем функция вызывается с одним аргументом для каждого параметра:

 

multiply(firstNumber: 10, secondNumber: 5)


Console Output:
The result is 50.

 

Ярлыки аргументов

Пока что ярлыки для аргументов, передаваемых функции, совпадают с именами параметров, которые она использовала внутри. В следующем примере firstName используется как внутри функции, так и при вызове функции:

 

func sayHello(firstName: String) {
  print(”Hello, \(firstName)!”)
}
 
sayHello(firstName: “Aidyn”)

 

Но представьте, что вы хотите, чтобы ваша функция читалась немного более четко:

 

sayHello(to: “Miles”, and: “Riley”)

 

Ярлыки аргументов to и and заставляют функцию читаться очень четко: "Поздоровайся с Майлзом и Райли". Однако ознакомьтесь с реализацией этой функции:

 

func sayHello(to: String, and: String) {
  print(”Hello \(to) and \(and)”)
}

 

В теле функции to и and являются плохими именами для параметров. Чтобы имя параметра внутри функции отличалось от ярлыка, используемой для вызова функции, укажите отдельный ярлык аргумента (argument label) перед именем параметра. В приведенном ниже коде to является ярлыком аргумента для параметра person, в то время как and является ярлыком аргумента для параметра anotherPerson:

 

func sayHello(to person: String, and anotherPerson: String) {
  print(”Hello \(person) and \(anotherPerson))
}
 
sayHello(to: “Miles”, and: “Riley”)

 

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

 

print(”Hello, world!”)

 

Название функции уже дает очень четкое представление о том, что должно быть передано в качестве параметра. Было бы странно, если бы вам пришлось вызывать функцию следующим образом:

 

print(message: “Hello, world!”)

 

Чтобы опустить ярлык аргумента, используйте _. В следующем примере ярлык для параметра firstNumber опущен, в то время как ярлык to добавляет смысла и делает вызов функции более читабельным:

 

func add(_ firstNumber: Int, to secondNumber: Int) -> Int {
    return firstNumber + secondNumber
}
 
let total = add(14, to: 6)

 

Значения параметров по умолчанию

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

Как часть определения функции, вы можете указать значение по умолчанию для любого параметра. Таким образом, вы можете вызвать функцию с параметром или без него. Если параметр не указан, функция просто использует значение по умолчанию.

 

func display(teamName: String, score: Int = 0) {
  print(”\(teamName): \(score))
}
 
display(teamName: “Wombats”, score: 100) // ”Wombats: 100”
display(teamName: “Wombats”) // ”Wombats: 0”

 

Для определения функции со значениями параметров по умолчанию и ярлыками аргументов необходим определенный уровень мышления. Компилятор может сделать только так много, когда делает вывод о том, что вы вызываете. Если вы смешиваете значения по умолчанию и параметры без ярлыков аргументов, вам необходимо проверить, что каждый вариант вызова функции может быть выведен.

Например, компилятор не может определить, какой вариант вашей функции вызывать, если он определен следующим образом:

 

func displayTeam(_ teamName: String, _ teamCaptain: String = "TBA", _ hometown: String, score: Int = 0) {
  // ...
}
 
displayTeam("Dodgers", "LA") // ERROR: Missing argument for parameter #3 in call

 

Возможно, вам покажется очевидным, что вы хотите, чтобы функция использовала значение по умолчанию “TBA” для teamCaptain и присвоила “Dodgers” teamName, а “LA” - hometown. Но компилятор распознает только три строковых параметра без ярлыков аргументов и только два значения для присвоения. Он не может предполагать, что вы намеревались использовать значение по умолчанию для teamCaptain.

Лучше всего оставлять аргументы со значениями по умолчанию в конце подписи функции и всегда указывать ярлык аргумента. В приведенном выше примере компилятор был бы удовлетворен, если бы у teamCaptain был ярлык аргумента.

 

func displayTeam(_ teamName: String, _ hometown: String, teamCaptain: String = "TBA", score: Int = 0)

 

Возвращаемые значения

Маловероятно, что вы всегда захотите печатать “Результат есть” перед результатом из multiply. Вместо этого было бы разумнее, если бы функция просто возвращала новое значение. Для этого вам нужно настроить объявление функции так, чтобы оно имело возвращаемое значение, и указать тип значения. Вы узнали, что умножение двух типов Int всегда приводит к Int, так что это возвращаемый тип, который вы будете использовать.

 

func multiply(firstNumber: Int, secondNumber: Int) -> Int

 

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

 

func multiply(firstNumber: Int, secondNumber: Int) -> Int {
  let result = firstNumber * secondNumber
  return result
}

 

Вместо того, чтобы умножать значения, сохранять новое значение в result и немедленно возвращать его, функция также может быть записана без константы:

 

func multiply(firstNumber: Int, secondNumber: Int) -> Int {
  return firstNumber * secondNumber
}

 

Начиная с Swift 5.1, вы даже можете опустить ключевое слово return для функций, которые имеют однострочную реализацию. Поскольку multiply(firstNumber:secondNumber:) имеет возвращаемый тип и только одну строку кода в его теле, результат этого выражения используется в качестве возвращаемого значения.

 

func multiply(firstNumber: Int, secondNumber: Int) -> Int {
  firstNumber * secondNumber
}

 

Чтобы вызвать эту функцию и использовать возвращаемое значение, вы можете присвоить возвращаемое значение константе:

 

let my Result = multiply(firstNumber: 10, secondNumber: 5)
 //myResult = 50 
print(”10 * 5 is \(myResult))

 

Если вам больше никогда не понадобится использовать myResult в будущем, вы можете использовать функцию внутри инструкции print и пропустить присвоение значения константе:

 

print(”10 * 5 is \(multiply(firstNumber: 10, secondNumber: 5)))

 

Лабораторная работа

Откройте и завершите упражнения в Lab—Functions.playground.

Подключение к дизайну

Откройте рабочую книгу по дизайну приложения и просмотрите раздел Карты, где вы определили функции для своего приложения. Как они могут соответствовать функциям в коде вашего приложения? Подумайте о том, какую информацию может потребоваться использовать вашему приложению, и подумайте о том, как вы можете вызывать функцию несколько раз с разной информацией. Добавьте комментарии в раздел карты или в новый пустой слайд в конце документа. Можете ли вы описать или написать псевдокод для функций?

В примере приложения Go Green для рабочей книги каждый раз, когда пользователь регистрирует элемент, он классифицирует его как мусор или переработку, и приложение обновляет график. Это было бы отличным местом для использования функции, поскольку задача регистрации элемента - это то, что будет выполняться снова и снова.

 


Отрывок из книги
Develop in Swift Fundamentals
Apple Education
https://books.apple.com/ru/book/develop-in-swift-fundamentals/id1581182804

Information

Apple, the Apple logo, Apple Books, Apple TV, Apple Watch, Cocoa, Cocoa Touch, Finder, Handoff, HealthKit, iPad, iPad Pro, iPhone, iPod touch, Keynote, Mac, macOS, Numbers, Objective-C, Pages, Photo Booth, Safari, Siri, Spotlight, Swift, tvOS, watchOS, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. App Store and iBooks Store are service marks of Apple Inc., registered in the U.S. and other countries. ​
The Bluetooth® word mark and logos are registered trademarks owned by Bluetooth SIG, Inc. and any use of such marks by Apple is under license. ​
IOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license. ​
Other product and company names mentioned herein may be trademarks of their respective companies.