web-dev-qa-db-fra.com

Contrainte de type générique pour le type numérique uniquement

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.

30
nalyd88

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)
26
Martin Gordon

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.

12
DeFrenZ

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.

2
Yawar

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)
0
Aky