Funciones genéricas
Parte de la sección Programación orientada a objetos del Journey de Swift de Coddy. Lección 34 de 57.
Una función genérica funciona con cualquier tipo. El marcador de posición entre corchetes angulares, a menudo T, representa el tipo que utiliza quien llama a la función, y Swift lo completa en cada llamada:
func firstAndLast<T>(_ items: [T]) -> [T] {
guard let first = items.first, let last = items.last else { return [] }
return [first, last]
}
print(firstAndLast([3, 8, 1]))
print(firstAndLast(["a", "b", "c"]))Salida:
[3, 1]
["a", "c"]Dentro de la función no se sabe nada sobre T, por lo que solo se permiten las operaciones que funcionan para cualquier tipo. Una restricción como T: Comparable permite hacer más cosas; en este caso, el operador <:
func largest<T: Comparable>(_ items: [T]) -> T? {
guard var best = items.first else { return nil }
for item in items where item > best { best = item }
return best
}
print(largest([4, 9, 2])!)
print(largest(["pear", "apple", "zucchini"])!)Salida:
9
zucchiniLos genéricos conservan el tipo exacto, a diferencia de Any. El resultado de largest sobre [Int] es un Int?, por lo que puede usarse en operaciones aritméticas sin conversión de tipos:
func largest<T: Comparable>(_ items: [T]) -> T? {
items.max()
}
let top = largest([3, 7, 5]) ?? 0
print(top * 10)Salida:
70Una función puede tener varios marcadores de posición, y las restricciones pueden nombrar protocolos propios:
protocol Scored { var score: Int { get } }
struct Player: Scored { let name: String; let score: Int }
struct Team: Scored { let score: Int }
func total<T: Scored>(_ items: [T]) -> Int {
items.reduce(0) { $0 + $1.score }
}
func pair<A, B>(_ a: A, _ b: B) -> String { "\(a) & \(b)" }
print(total([Player(name: "a", score: 3), Player(name: "b", score: 4)]))
print(total([Team(score: 10)]))
print(pair(1, "one"))Salida:
7
10
1 & oneDesafío
FácilEscribe la función genérica countWhere(_:_:) que recibe un array de cualquier tipo y un predicado (T) -> Bool, y devuelve cuántos elementos cumplen la condición, y mostCommon(_:), que recibe un array de cualquier tipo Hashable y devuelve su elemento más frecuente (el que aparece primero en el array cuando hay empate en los conteos), o nil si el array está vacío.
El código proporcionado lee una línea de palabras separadas por comas y una línea de números. Imprime la cantidad de palabras con más de 3 caracteres, la palabra más frecuente, la cantidad de números pares y el número más frecuente.
Tu código debe estar en Functions.swift. main.swift contiene el código proporcionado de entrada/salida y no se puede editar.
Pruébalo tú mismo
// Código de entrada/salida suministrado: déjalo como está
var input: [String] = []
while let line = readLine() { input.append(line) }
let words = input[0].split(separator: ",").map(String.init)
let numbers = input[1].split(separator: ",").map { Int($0)! }
print(countWhere(words) { $0.count > 3 })
print(mostCommon(words) ?? "none")
print(countWhere(numbers) { $0 % 2 == 0 })
print(mostCommon(numbers).map { String($0) } ?? "none")
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Clases y objetos
Trabajar con archivosDefinir clasesMétodos y selfInicializadoresLas clases son referenciasRepaso: tarjeta de biblioteca4Encapsulación
Control de accesoSolo lectura desde fueraProtección del estadoInicializadores que pueden fallarRepaso - Cuenta bancaria7Polimorfismo y genéricos
PolimorfismoConversión de tiposFunciones genéricasTipos genéricosRepaso - Calculadora de formas2Structs y tipos por valor
StructsSemántica de valoresMétodos mutablesStruct o claseRepaso - elemento del inventario5Herencia
SubclasesSobrescritura de métodosInicializadores y superfinal y jerarquíasRepaso: jerarquía de empleados8Protocolos estándar
CustomStringConvertibleEquatableComparableHashableRepaso - Ordenamiento personalizado11Proyecto: Gestión de bibliotecas
Libros y miembrosPréstamo de librosPractica por tu cuenta: Playground de Swift