J'essaie de comprendre comment implémenter une contrainte de type pour une classe générique (dans Swift) qui limitera les types génériques à des types numériques. Par exemple, Double, Int, etc., mais pas de chaîne. Merci pour toute aide.
Vous pouvez spécifier des contraintes de type (utilisant à la fois des classes et des protocoles) pour une classe générique (la même syntaxe s'applique aux fonctions) à l'aide de crochets angulaires:
class Foo<T: Equatable, U: Comparable> { }
Pour spécifier plusieurs exigences sur un même type, utilisez une clause where
:
class Foo<T: UIViewController where T: UITableViewDataSource, T: UITextFieldDelegate> { }
Cependant, il ne semble pas que vous puissiez spécifier des exigences facultatives dans une clause de paramètre générique. Une solution possible consiste donc à créer un protocole que tous les types numériques implémentent via des extensions, puis à contraindre votre classe à cette exigence:
protocol Numeric { }
extension Float: Numeric {}
extension Double: Numeric {}
extension Int: Numeric {}
class NumberCruncher<C1: Numeric> {
func echo(num: C1)-> C1 {
return num
}
}
NumberCruncher<Int>().echo(42)
NumberCruncher<Float>().echo(3.14)
Strideable
est le protocole standard smallest auquel chaque type de numéro standard est conforme, mais il possède également un peu plus de types s'y conformant . http://swiftdoc.org/protocol/Strideable/hierarchy/
Ou vous pouvez utiliser IntegerType
et FloatingPointType
.
Vous pouvez rouler le vôtre avec un enum:
enum Numeric {
case NInt(Int)
case NUInt(UInt)
case NFloat(Float)
case NDouble(Double)
}
Puis utilisez-le dans votre code:
func myFunc(x: Numeric) -> Numeric {
switch x {
case let NInt(i):
return i + 1
case let NUInt(u):
return u + 1
case let NFloat(f):
return f + 1
case let NDouble(d):
return d + 1
}
}
Ou vous pouvez simplement utiliser NSNumber, qui regroupe plusieurs types numériques en un type de couverture.
Comme mentionné dans ici et ici , le protocole Numeric
fait maintenant partie de Swift 4. Par conséquent, vous pouvez surcharger +
pour des n-uplets numériques comme suit:
func +<T : Numeric> (x: (T, T), y: (T, T)) -> (T, T) {
return (x.0 + y.0, x.1 + y.1)
}
(1,1) + (2,3) // (3, 4) : (Int, Int)
(1.25, 1.5) + (2.5, 2.25) // (3.75, 3.75) : (Double, Double)