Swift Language
Funkcje
Szukaj…
Podstawowe użycie
Funkcje można zadeklarować bez parametrów lub wartości zwracanej. Jedyną wymaganą informacją jest nazwa (w tym przypadku hello
).
func hello()
{
print("Hello World")
}
Wywołaj funkcję bez parametrów, wpisując jej nazwę, a następnie pustą parę nawiasów.
hello()
//output: "Hello World"
Funkcje z parametrami
Funkcje mogą przyjmować parametry, aby można było modyfikować ich funkcje. Parametry podano jako listę oddzieloną przecinkami, ze zdefiniowanymi ich typami i nazwami.
func magicNumber(number1: Int)
{
print("\(number1) Is the magic number")
}
Uwaga: Składnia \(number1)
jest podstawową interpolacją ciągu znaków i służy do wstawiania liczby całkowitej do ciągu.
Funkcje z parametrami są wywoływane przez określenie funkcji według nazwy i podanie wartości wejściowej typu użytego w deklaracji funkcji.
magicNumber(5)
//output: "5 Is the magic number
let example: Int = 10
magicNumber(example)
//output: "10 Is the magic number"
Można użyć dowolnej wartości typu Int.
func magicNumber(number1: Int, number2: Int)
{
print("\(number1 + number2) Is the magic number")
}
Gdy funkcja używa wielu parametrów, nazwa pierwszego parametru nie jest wymagana dla pierwszego, ale dotyczy kolejnych parametrów.
let ten: Int = 10
let five: Int = 5
magicNumber(ten,number2: five)
//output: "15 Is the magic number"
Użyj nazw parametrów zewnętrznych, aby wywołania funkcji były bardziej czytelne.
func magicNumber(one number1: Int, two number2: Int)
{
print("\(number1 + number2) Is the magic number")
}
let ten: Int = 10
let five: Int = 5
magicNumber(one: ten, two: five)
Ustawienie wartości domyślnej w deklaracji funkcji umożliwia wywołanie funkcji bez podawania wartości wejściowych.
func magicNumber(one number1: Int = 5, two number2: Int = 10)
{
print("\(number1 + number2) Is the magic number")
}
magicNumber()
//output: "15 Is the magic number"
Zwracane wartości
Funkcje mogą zwracać wartości, określając typ po liście parametrów.
func findHypotenuse(a: Double, b: Double) -> Double
{
return sqrt((a * a) + (b * b))
}
let c = findHypotenuse(3, b: 5)
//c = 5.830951894845301
Funkcje mogą również zwracać wiele wartości za pomocą krotek.
func maths(number: Int) -> (times2: Int, times3: Int)
{
let two = number * 2
let three = number * 3
return (two, three)
}
let resultTuple = maths(5)
//resultTuple = (10, 15)
Błędy rzucania
Jeśli chcesz, aby funkcja mogła zgłaszać błędy, musisz dodać słowo kluczowe throws
po nawiasach zawierających argumenty:
func errorThrower()throws -> String {}
Jeśli chcesz zgłosić błąd, użyj słowa kluczowego throw
:
func errorThrower()throws -> String {
if true {
return "True"
} else {
// Throwing an error
throw Error.error
}
}
Jeśli chcesz wywołać funkcję, która może wygenerować błąd, trzeba użyć try
słowa kluczowego w do
bloku:
do {
try errorThrower()
}
Więcej informacji o błędach Swift: Błędy
Metody
Metody instancji to funkcje należące do instancji typu w Swift ( klasa , struktura , wyliczenie lub protokół ). Metody typu są wywoływane na samym typie.
Metody instancji
Metody instancji są definiowane za pomocą deklaracji func
w definicji typu lub w rozszerzeniu .
class Counter {
var count = 0
func increment() {
count += 1
}
}
Metoda instancji increment()
jest wywoływana w instancji klasy Counter
:
let counter = Counter() // create an instance of Counter class
counter.increment() // call the instance method on this instance
Metody typu
Metody typu są definiowane za pomocą static func
słów kluczowych static func
. (W przypadku klas class func
definiuje metodę typu, którą można zastąpić podklasami).
class SomeClass {
class func someTypeMethod() {
// type method implementation goes here
}
}
SomeClass.someTypeMethod() // type method is called on the SomeClass type itself
Parametry wejściowe
Funkcje mogą modyfikować przekazane im parametry, jeśli są oznaczone słowem kluczowym inout
. Przy przekazywaniu parametru inout
do funkcji wywołujący musi dodać znak &
do przekazywanej zmiennej.
func updateFruit(fruit: inout Int) {
fruit -= 1
}
var apples = 30 // Prints "There's 30 apples"
print("There's \(apples) apples")
updateFruit(fruit: &apples)
print("There's now \(apples) apples") // Prints "There's 29 apples".
Umożliwia to zastosowanie semantyki odniesienia do typów, które normalnie miałyby semantykę wartości.
Składnia końcowego zamknięcia
Gdy ostatnim parametrem funkcji jest zamknięcie
func loadData(id: String, completion:(result: String) -> ()) {
// ...
completion(result:"This is the result data")
}
funkcję można wywołać za pomocą składni końcowego zamykania
loadData("123") { result in
print(result)
}
Operatory to funkcje
Operatory takie jak +
, -
, ??
są rodzajem funkcji nazwanych za pomocą symboli zamiast liter. Są wywoływane inaczej niż funkcje:
- Prefiks:
- x
- Infix:
x + y
- Postfiks:
x ++
Możesz przeczytać więcej o podstawowych operatorach i operatorach zaawansowanych w Swift Programming Language.
Parametry Variadic
Czasami nie jest możliwe podanie liczby parametrów, których może potrzebować funkcja. Rozważ funkcję sum
:
func sum(_ a: Int, _ b: Int) -> Int {
return a + b
}
Działa to dobrze, aby znaleźć sumę dwóch liczb, ale aby znaleźć sumę trzech, musielibyśmy napisać inną funkcję:
func sum(_ a: Int, _ b: Int, _ c: Int) -> Int {
return a + b + c
}
i jeden z czterema parametrami potrzebowałby innego i tak dalej. Swift umożliwia zdefiniowanie funkcji o zmiennej liczbie parametrów za pomocą sekwencji trzech okresów: ...
Na przykład,
func sum(_ numbers: Int...) -> Int {
return numbers.reduce(0, combine: +)
}
Zwróć uwagę, w jaki sposób parametr numbers
, który jest variadic, zlewa się w jedną Array
typu [Int]
. Zasadniczo jest to prawda, różne parametry typu T...
są dostępne jako [T]
.
Tę funkcję można teraz wywołać w następujący sposób:
let a = sum(1, 2) // a == 3
let b = sum(3, 4, 5, 6, 7) // b == 25
Parametr variadic w Swift nie musi znajdować się na końcu listy parametrów, ale może być tylko jeden w podpisie każdej funkcji.
Czasami wygodnie jest ustawić minimalny rozmiar liczby parametrów. Na przykład nie ma sensu przyjmowanie sum
żadnych wartości. Łatwym sposobem na wymuszenie tego jest umieszczenie niektórych nie-wariadycznych wymaganych parametrów, a następnie dodanie parametru variadic po. Aby upewnić się, że sum
można wywołać tylko z co najmniej dwoma parametrami, możemy napisać
func sum(_ n1: Int, _ n2: Int, _ numbers: Int...) -> Int {
return numbers.reduce(n1 + n2, combine: +)
}
sum(1, 2) // ok
sum(3, 4, 5, 6, 7) // ok
sum(1) // not ok
sum() // not ok
Indeksy dolne
Klasy, struktury i wyliczenia mogą definiować indeksy dolne, które są skrótami do uzyskiwania dostępu do elementów składowych kolekcji, listy lub sekwencji.
Przykład
struct DaysOfWeek {
var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
subscript(index: Int) -> String {
get {
return days[index]
}
set {
days[index] = newValue
}
}
}
Wykorzystanie indeksu dolnego
var week = DaysOfWeek()
//you access an element of an array at index by array[index].
debugPrint(week[1])
debugPrint(week[0])
week[0] = "Sunday"
debugPrint(week[0])
Opcje indeksów dolnych:
Indeksy dolne mogą przyjmować dowolną liczbę parametrów wejściowych, a te parametry wejściowe mogą być dowolnego typu. Indeksy dolne mogą również zwracać dowolny typ. Indeksy dolne mogą wykorzystywać parametry zmienne i parametry wariadyczne, ale nie mogą używać parametrów wejściowych ani domyślnych wartości parametrów.
Przykład:
struct Food {
enum MealTime {
case Breakfast, Lunch, Dinner
}
var meals: [MealTime: String] = [:]
subscript (type: MealTime) -> String? {
get {
return meals[type]
}
set {
meals[type] = newValue
}
}
}
Stosowanie
var diet = Food()
diet[.Breakfast] = "Scrambled Eggs"
diet[.Lunch] = "Rice"
debugPrint("I had \(diet[.Breakfast]) for breakfast")
Funkcje z zamknięciami
Korzystanie z funkcji, które przyjmują i wykonują zamknięcia, może być niezwykle przydatne do wysyłania bloku kodu do wykonania w innym miejscu. Możemy zacząć od zezwolenia naszej funkcji na opcjonalne zamknięcie, które (w tym przypadku) zwróci Void
.
func closedFunc(block: (()->Void)? = nil) {
print("Just beginning")
if let block = block {
block()
}
}
Teraz, gdy nasza funkcja została zdefiniowana, wywołajmy ją i przekażmy kod:
closedFunc() { Void in
print("Over already")
}
Używając końcowego zamknięcia w naszym wywołaniu funkcji, możemy przekazać kod (w tym przypadku print
), który zostanie wykonany w pewnym momencie w ramach naszej funkcji closedFunc()
.
Dziennik powinien zostać wydrukowany:
Dopiero zaczynam
Już skończone
Bardziej konkretny przypadek użycia tego może obejmować wykonanie kodu między dwiema klasami:
class ViewController: UIViewController {
override func viewDidLoad() {
let _ = A.init(){Void in self.action(2)}
}
func action(i: Int) {
print(i)
}
}
class A: NSObject {
var closure : ()?
init(closure: (()->Void)? = nil) {
// Notice how this is executed before the closure
print("1")
// Make sure closure isn't nil
self.closure = closure?()
}
}
Dziennik powinien zostać wydrukowany:
1
2)
Przekazywanie i zwracanie funkcji
Następująca funkcja zwraca inną funkcję w wyniku, którą można później przypisać do zmiennej i wywołać:
func jediTrainer () -> ((String, Int) -> String) {
func train(name: String, times: Int) -> (String) {
return "\(name) has been trained in the Force \(times) times"
}
return train
}
let train = jediTrainer()
train("Obi Wan", 3)
Rodzaje funkcji
Każda funkcja ma swój własny typ funkcji, złożony z typów parametrów i typu zwracanego przez samą funkcję. Na przykład następująca funkcja:
func sum(x: Int, y: Int) -> (result: Int) { return x + y }
ma typ funkcji:
(Int, Int) -> (Int)
Typy funkcji mogą być zatem używane jako typy parametrów lub jako typy zwrotne dla funkcji zagnieżdżania.