as

La pseudo-méthode as limite les types d'une expression. Par exemple:

if une_condition
  a = 1
else
  a = "hello"
end

# a : Int32 | String

Dans le code précédent, a est l'union de Int32 | String. Si pour une quelconque raison nous sommes sûres que a est un Int32 après le if, on peut forcer le compilateur pour le traiter comme tel:

a_as_int = a.as(Int32)
a_as_int.abs          # fonctionne, le compilateur sait que a_as_int est de type Int32

La pseudo-méthode as effectue une vérification à l'exécution: Si a n'était pas un Int32, une exception serait relevée.

L'argument de l'expression est un type.

Il est impossible pour un type d'être limité à un autre type, une erreur à la compilation est retournée:

1.as(String) # Erreur à la compilation

Note: vous ne pouvez utiliser as pour convertir un type en un type qui n'a aucun rapport: as est comme un cast dans les autres langages. Les méthodes sur les entiers, flottants et caractères sont fournies pour ces conversions. Alternativement, utilisez le typage de pointeur comme expliqué ci-dessous.

Conversion entre types de pointeur

La pseudo-méthode as permet également de transtyper entre types de pointeur:

ptr = Pointer(Int32).malloc(1)
ptr.as(Int8*)                    #:: Pointer(Int8)

Dans ce cas, aucune vérification à l'exécution n'est faite: les pointeurs sont dangereux (unsafe) et cette forme de typage est généralement utilisée seulement pour les liaisons C et le code bas-niveau.

Conversion entre types de pointeur et autres types

La conversion entre types de pointeur et types Référence est également possible:

array = [1, 2, 3]

# object_id retourne l'adresse d'un objet en mémoire,
# alors on crée un pointeur avec cette adresse
ptr = Pointer(Void).new(array.object_id)

# Maintenant on 'cast' ce pointeur avec le même type, et
# on devrait avoir la même valeur
array2 = ptr.as(Array(Int32))
array2.same?(array) #=> true

Aucune vérification à la compilation n'est faite ici car, à nouveau, des pointeurs sont utilisés. L'utilité de ce typage est encore plus rare que pour le précédent, mais permet d'implémenter certains types centraux (comme String) dans Crystal lui-même, et permet également de passer un type Référence à des fonctions C en le transtypant vers un pointeur vide.

Utilisation du transtypage pour un type plus important

La pseudo-méthode as peut-être utilisée pour transtyper une expression en un type "plus important". Par exemple:

a = 1
b = a.as(Int32 | Float64)
b #:: Int32 | Float64

Ce qui précéde peut sembler avoir une utilisation limitée, mais elle est pourtant utile, par exemple, lors de la correspondance d'un tableau d'éléments:

ary = [1, 2, 3]

# Nous voulons créer un tableau 1, 2, 3 de Int32 | Float64
ary2 = ary.map { |x| x.as(Int32 | Float64) }

ary2 #:: Array(Int32 | Float64)
ary2 << 1.5 # OK

La méthode Array#map utilise le type de bloc comme type générique pour l'Array. Sans la pseudo-méthode as, le type inféré aurait été Int32 et n'aurait pas été capable d'y ajouter Float64.

Utilisation lorsque le compilateur ne peut inférer le type d'un bloc

Des fois le compilateur ne peut inférer le type d'un bloc. Ceci peut arriver dans des appels récursifs qui dépendent les uns des autres. Dans ce cas vous pouvez utiliser as pour lui faire connaître le type:

un_appel { |v| v.method.as(ExpectedType) }

results matching ""

    No results matching ""