2
出於好奇,並且瞭解了一些關於Crystal的一般結構的信息,我一直在尋找一些反射特性,以便更好地理解繼承鏈是如何構建的。獲取有關繼承鏈的信息
我在想像ruby的superclass,ancestors或included_modules方法。
有沒有類似Crystal語言的東西?
此外,有一些圖表可以讓我看到大圖。
出於好奇,並且瞭解了一些關於Crystal的一般結構的信息,我一直在尋找一些反射特性,以便更好地理解繼承鏈是如何構建的。獲取有關繼承鏈的信息
我在想像ruby的superclass,ancestors或included_modules方法。
有沒有類似Crystal語言的東西?
此外,有一些圖表可以讓我看到大圖。
晶體中的元編程是使用macros實現的。
宏是在編譯時接收AST節點並生成粘貼到程序中的代碼的方法。
晶體已經實現了superclass
和ancestors
,它們在編譯時返回結果。所以你可以這樣做:
pp({{ MyClass.superclass }})
pp({{ MyClass.ancestors }})
爲了方便,檢查繼承你可以編寫自己的宏。銘記學習的目的,它可能是這樣的:
class Class
def superclass
{{ @type.superclass }}
end
def ancestors
{% if @type.ancestors.size > 0 %}
{{ @type.ancestors }}
{% else %}
[] of Nil
{% end %}
end
def included_modules
{% if @type.ancestors.any? { |a| a.class.stringify.ends_with?(":Module") } %}
{{ @type.ancestors.select { |a| a.class.stringify.ends_with?(":Module") } }}
{% else %}
[] of Nil
{% end %}
end
def inheritance_chain
String.build do |chain|
cls = self
chain << cls
while !(cls = cls.superclass).nil?
chain << " > #{cls}"
end
end
end
end
然後,你可以做的檢查:
class A
end
module B
end
require "crystal/system/random"
class C < A
include B
include Crystal::System::Random
end
C.name # => "C"
C.superclass # => A
C.ancestors # => [Crystal::System::Random, B, A, Reference, Object]
C.included_modules # => [Crystal::System::Random, B]
A.included_modules # => []
如果你走的更遠:
C.superclass # => A
C.superclass.try &.superclass # => Reference
C.superclass.try &.superclass.try &.superclass # => Object
C.superclass.try &.superclass.try &.superclass.try &.superclass # => nil
而現在使用inheritance_chain
:
Int32.inheritance_chain # => "Int32 > Int > Number > Value > Object"
String.inheritance_chain # => "String > Reference > Object"
Float64.inheritance_chain # => "Float64 > Float > Number > Value > Object"
Array(Bool).inheritance_chain # => "Array(Bool) > Reference > Object"
Hash(Bool, Bool).inheritance_chain # => "Hash(Bool, Bool) > Reference > Object"
Tuple(Char).inheritance_chain # => "Tuple(Char) > Struct > Value > Object"
NamedTuple(s: String, b: Bool).inheritance_chain # => "NamedTuple(s: String, b: Bool) > Struct > Value > Object"
Nil.inheritance_chain # => "Nil > Value > Object"
Regex.inheritance_chain # => "Regex > Reference > Object"
Symbol.inheritance_chain # => "Symbol > Value > Object"
Proc(Int32).inheritance_chain # => "Proc(Int32) > Struct > Value > Object"
Set(String).inheritance_chain # => "Set(String) > Struct > Value > Object"
Exception.inheritance_chain # => "Exception > Reference > Object"
Class.inheritance_chain # => "Class > Value > Object"
# union
alias UnionType = Int32 | Nil | String
UnionType.inheritance_chain # => "(Int32 | String | Nil) > Value > Object"
# nilable
Int32?.inheritance_chain # => "(Int32 | Nil) > Value > Object"
# pointer
alias Int32Ptr = Int32*
Int32Ptr.inheritance_chain # => "Pointer(Int32) > Struct > Value > Object"
# ...
太好了swer!順便說一下,是否有可能看看這些方法的來源? (在這裏嘗試https://github.com/crystal-lang/crystal/blob/e2a1389e8165fb097c785524337d7bb7b550a086/src/compiler/crystal/macros.cr#L1508,但他們只是爲了文檔的目的) – opensas
@opensas一些相關的實現是[這裏](https://github.com/crystal-lang/crystal/blob/master/src/compiler/crystal/macros/methods.cr#L1523-L1532)。但是,老實說,我不明白它是如何工作的。也許最好直接在GitHub(或Gitter)上提問... –