0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Run-time Types

Last updated at Posted at 2024-10-21

型は実行時に表現できます。型値を作成するには、コンストラクタ関数 Type() を使用します。この関数は、静的型を型引数として受け取ります。
これは、例えばSwiftのT.self、KotlinのT::class/KClass、JavaのT.class/Classに似ています。
例えば、実行時に型 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
    }
}

翻訳元->https://cadence-lang.org/docs/language/run-time-types

Flow BlockchainのCadence version1.0ドキュメント (Run-time Types)

Previous << Core Events

Next >> Built-in Functions

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?