Previous << Core Events
Next >> Built-in Functions
型は実行時に表現できます。型値を作成するには、コンストラクタ関数 Type<T>()
を使用します。この関数は、静的型を型引数として受け取ります。
これは、例えばSwiftのT.self
、KotlinのT::class
/KClass<T>
、JavaのT.class
/Class<T>
に似ています。
例えば、実行時に型 Int
を表現するには:
let intType: Type = Type<Int>()
これは、組み込み型とユーザー定義型の両方で機能します。例えば、リソースの型値を取得するには:
resource Collectible {}
let collectibleType = Type<@Collectible>()
/* `collectibleType` has type `Type` */
型の値は比較可能です。
Type<Int>() == Type<Int>()
Type<Int>() != Type<String>()
view fun isSubtype(of: Type): Bool
メソッドを使用すると、実行時に型の値を比較することができます。
Type<Int>().isSubtype(of: Type<Int>())
/* true */
Type<Int>().isSubtype(of: Type<String>())
/* false */
Type<Int>().isSubtype(of: Type<Int?>())
/* true */
実行時の型の完全修飾型識別子を取得するには、let identifier: String
フィールドを使用します。
let type = Type<Int>()
type.identifier /* is "Int" */
/* in account 0x1 */
struct Test {}
let type = Type<Test>()
type.identifier /* is "A.0000000000000001.Test" */
Getting the Type from a Value
view fun getType(): Type
というメソッドを使用すると、値の実行時型を取得できます。
let something = "hello"
let type: Type = something.getType()
/* `type` is `Type<String>()` */
このメソッドは、静的型ではなく、オブジェクトの具体的な実行時の型を返します。
/* Declare a variable named `something` that has the *static* type `AnyResource`
* and has a resource of type `Collectible`
*/
let something: @AnyResource <- create Collectible()
/* The resource's concrete run-time type is `Collectible` */
let type: Type = something.getType()
/* `type` is `Type<@Collectible>()` */
Constructing a Run-time Type
実行時の型は、組み込みのコンストラクタ関数を使用して型識別子文字列から構築することもできます。
view fun CompositeType(_ identifier: String): Type?
view fun InterfaceType(_ identifier: String): Type?
view fun IntersectionType(types: [String]): Type?
型識別子(またはIntersectionType
の場合はインターフェースの識別子のリスト)が与えられた場合、これらの関数は名義型を検索し、その実行時等価値を生成します。与えられた識別子がいずれの型にも一致しない場合、または(IntersectionType
の場合)与えられた識別子の組み合わせが静的に型チェックを通らない場合、これらの関数はnil
を生成します。
struct Test: I {}
struct interface I {}
let type: Type = CompositeType("A.0000000000000001.Test")
/* `type` is `Type<Test>` */
let type2: Type = IntersectionType(
restrictions: ["A.0000000000000001.I"]
)
/* `type2` is `Type<{I}>` */
その他の組み込み関数は、他の実行型から複合型を構築します。
view fun OptionalType(_ type: Type): Type
view fun VariableSizedArrayType(_ type: Type): Type
view fun ConstantSizedArrayType(type: Type, size: Int): Type
view fun FunctionType(parameters: [Type], return: Type): Type
/* returns `nil` if `key` is not valid dictionary key type */
view fun DictionaryType(key: Type, value: Type): Type?
/* returns `nil` if `type` is not a reference type */
view fun CapabilityType(_ type: Type): Type?
view fun ReferenceType(entitlements: [String], type: Type): Type?
Asserting the Type of a Value
view fun isInstance(_ type: Type): Bool
メソッドは、値が特定の型であるかどうかを、具体的な実行時型を使用して、サブタイピングルール(原文: subtyping rules)を考慮しながら確認するために使用できます。
/* Declare a variable named `collectible` that has the *static* type `Collectible`
* and has a resource of type `Collectible`
*/
let collectible: @Collectible <- create Collectible()
/* The resource is an instance of type `Collectible`,
* because the concrete run-time type is `Collectible`
*/
collectible.isInstance(Type<@Collectible>())
/* is `true` */
/* The resource is an instance of type `AnyResource`,
* because the concrete run-time type `Collectible` is a subtype of `AnyResource`
*/
collectible.isInstance(Type<@AnyResource>())
/* is `true` */
/* The resource is *not* an instance of type `String`,
* because the concrete run-time type `Collectible` is *not* a subtype of `String`
*/
collectible.isInstance(Type<String>())
/* is `false` */
オブジェクトの具体的な実行時型が使用され、静的型ではないことに注意してください。
/* Declare a variable named `something` that has the *static* type `AnyResource`
* and has a resource of type `Collectible`
*/
let something: @AnyResource <- create Collectible()
/* The resource is an instance of type `Collectible`,
* because the concrete run-time type is `Collectible`
*/
something.isInstance(Type<@Collectible>())
/* is `true` */
/* The resource is an instance of type `AnyResource`,
* because the concrete run-time type `Collectible` is a subtype of `AnyResource`
*/
something.isInstance(Type<@AnyResource>())
/* is `true` */
/* The resource is *not* an instance of type `String`,
* because the concrete run-time type `Collectible` is *not* a subtype of `String`
*/
something.isInstance(Type<String>())
/* is `false` */
例えば、これによりマーケットプレイス販売リソースを実装することができます。
access(all)
resource SimpleSale {
/** The resource for sale.
* Once the resource is sold, the field becomes `nil`.
*/
access(all)
var resourceForSale: @AnyResource?
/** The price that is wanted for the purchase of the resource. */
access(all)
let priceForResource: UFix64
/** The type of currency that is required for the purchase. */
access(all)
let requiredCurrency: Type
access(all)
let paymentReceiver: Capability<&{FungibleToken.Receiver}>
/** `paymentReceiver` is the capability that will be borrowed
* once a valid purchase is made.
* It is expected to target a resource that allows depositing the paid amount
* (a vault which has the type in `requiredCurrency`).
*/
init(
resourceForSale: @AnyResource,
priceForResource: UFix64,
requiredCurrency: Type,
paymentReceiver: Capability<&{FungibleToken.Receiver}>
) {
self.resourceForSale <- resourceForSale
self.priceForResource = priceForResource
self.requiredCurrency = requiredCurrency
self.paymentReceiver = paymentReceiver
}
/** buyObject allows purchasing the resource for sale by providing
* the required funds.
* If the purchase succeeds, the resource for sale is returned.
* If the purchase fails, the program aborts.
*/
access(all)
fun buyObject(with funds: @FungibleToken.Vault): @AnyResource {
pre {
/* Ensure the resource is still up for sale */
self.resourceForSale != nil: "The resource has already been sold"
/* Ensure the paid funds have the right amount */
funds.balance >= self.priceForResource: "Payment has insufficient amount"
/* Ensure the paid currency is correct */
funds.isInstance(self.requiredCurrency): "Incorrect payment currency"
}
/* Transfer the paid funds to the payment receiver
* by borrowing the payment receiver capability of this sale resource
* and depositing the payment into it */
let receiver = self.paymentReceiver.borrow()
?? panic("failed to borrow payment receiver capability")
receiver.deposit(from: <-funds)
let resourceForSale <- self.resourceForSale <- nil
return <-resourceForSale
}
}
翻訳元
Flow BlockchainのCadence version1.0ドキュメント (Run-time Types)