如何覆盖另一个包中的类中的现有选择器

时间:2016-06-12 02:34:16

标签: smalltalk pharo

我正在使用Pharo 5.0。在某些情况下,我发现现有Pharo类中存在限制或可能存在错误(例如,DBXTalk / Garage或Regex-Core中的某些内容)。我希望能够修改我自己项目之外的类中存在的选择器或选择器集,并将其作为我的包的一部分。

我找到了一些关于如何在外部类中创建 new 选择器的说明,并将其移到我的包中(例如,如此{{3}所示) })。这非常酷。但在某些情况下,我实际上想修改外部类中的现有选择器,并且当我使用它时,我的该选择器的副本会覆盖外部类中的那个。我不希望修改现有的第三方或Pharo预先提供的包。

在GNU Smalltalk中,我可以将其作为进行类扩展的正常部分。例如:

Kernel.MatchingRegexResults extend [
    at: anIndex [
        "My updated version of the 'official' Kernel.MatchingRegexResults#at: selector"
        "This is part of my package so overrides the 'official' version"
        ...
    ]

    foo [
        "My new foo selector"
    ]
]

如何在Pharo 5.0中执行此操作?我做了很多搜索,但找不到办法。单词"延伸"或"覆盖"不会出现在 Pharo by Example Deep Into Pharo 书籍中。

2 个答案:

答案 0 :(得分:3)

请注意,除了Milan Vavra所写的内容之外,名为*YourPackage-(something)的协议中的每个方法都属于包YourPackage,无论该类属于哪个包。至少在Squeak中,有一种惯例是在*YourPackage-override协议中将方法重写为这样。 Pharo可能有类似的命名约定。 Move to package功能将方法移动到这种“已加星标”的协议。

但是,不鼓励使用此类覆盖,因为您不能让两个包同时为同一方法提供实现。 Monticello将尝试保留原始方法和重写方法(请参阅PackageInfo>>isOverrideCategory:的发件人),但仍有可能您的覆盖方法将被原始包的更新覆盖,否则您将错过原始方法的更新,可能会破坏事物。

“正确的方法”是重构原始包中的原始方法,以使其行为更容易定制。

答案 1 :(得分:2)

GNU Smalltalk语法中的代码

    #include<stdio.h>
    #include<stdlib.h>

    int main(void)
    {
     int a = 0;
     printf("Enter a number: ");
     scanf ("%d" ,&a);
     printf ("%d \n ",a);
return 0;
}

看起来像这样

Kernel.MatchingRegexResults extend [
    at: anIndex [
        "method body"
    ]
    foo [
        "My new foo selector"
    ]
]

在Pharo更改集中,可以从文件浏览器中归档。

但请注意,在两种情况下,GNU Smalltalk和Pharo Smalltalk,您实际上都在替换该类中方法的原始版本。

在GNU Smalltalk中,您可能不习惯保存图像,因此您可能认为extend语法不会修改原始类中的原始方法。

实际上确实如此。

使用GNU Smalltalk,每次运行gst时,通常都会使用相同的旧的未修改图像。 这是因为GNU Smalltalk中图像的默认位置不能写入普通用户。因此gst每次都读取相同的只读图像,您可以使用类定义和扩展在内存中修改它,修改后的图像仅在程序运行时暂时存在,并在程序退出时被丢弃。