类型转换
向上转换
因为 Python 是一种使用鸭子类型的语言,所以没有强制转换的概念。没有必要向上转换,本质上也没有向下转换
但是,Erg 是静态类型的,因此有时必须进行强制转换
一个简单的例子是 1 + 2.0
: +
(Int, Ratio) 或 Int(<: Add(Ratio, Ratio)) 操作在 Erg 语言规范中没有定义。这是因为 Int <: Ratio
,所以 1 向上转换为 1.0,即 Ratio 的一个实例
~~ Erg扩展字节码在BINARY_ADD中增加了类型信息,此时类型信息为Ratio-Ratio。在这种情况下,BINARY_ADD 指令执行 Int 的转换,因此没有插入指定转换的特殊指令。因此,例如,即使您在子类中重写了某个方法,如果您将父类指定为类型,则会执行类型强制,并在父类的方法中执行该方法(在编译时执行名称修改以引用父母的方法)。编译器只执行类型强制验证和名称修改。运行时不强制转换对象(当前。可以实现强制转换指令以优化执行)。~~
@Inheritable
Parent = Class()
Parent.
greet!() = print! "Hello from Parent"
Child = Inherit Parent
Child.
# Override 需要 Override 装饰器
@Override
greet!() = print! "Hello from Child"
greet! p: Parent = p.greet!()
parent = Parent.new()
child = Child.new()
parent # 来自Parent的问候!
child # 来自child的问候!
此行为不会造成与 Python 的不兼容。首先,Python 没有指定变量的类型,所以可以这么说,所有的变量都是类型变量。由于类型变量会选择它们可以适应的最小类型,因此如果您没有在 Erg 中指定类型,则可以实现与 Python 中相同的行为
@Inheritable
Parent = Class()
Parent.
greet!() = print! "Hello from Parent"
Child = Inherit Parent
Child.
greet!() = print! "Hello from Child" Child.
greet! some = some.greet!()
parent = Parent.new()
child = Child.new()
parent # 来自Parent的问候!
child # 来自child的问候!
您还可以使用 .from
和 .into
,它们会为相互继承的类型自动实现
assert 1 == 1.0
assert Ratio.from(1) == 1.0
assert 1.into<Ratio>() == 1.0
向下转换
由于向下转换通常是不安全的并且转换方法很重要,我们改为实现TryFrom.try_from
IntTryFromFloat = Patch Int
IntTryFromFloat.
try_from r: Float =
if r.ceil() == r:
then: r.ceil()
else: Error "conversion failed".