具有特征和函数重载的静态类型语言?

时间:2013-07-26 00:32:40

标签: templates generics multiple-inheritance overloading

是否存在任何语言:

  • 是静态(和强烈)键入的
  • 支持泛型(模板)
  • 支持traits / multiple inheritance / interface delegation
  • 允许函数重载(继承成员也是如此)

基本上,在伪代码中,我想要这个:

class Template<SomeType> { void function(SomeType i) {} }
class Composed extends Template<int>, Template<double> { };
Composed composed;
composed.function(3); //calls function(int)
composed.function(2.5); //calls function(double)

从wiki列表http://en.wikipedia.org/wiki/Multiple_inheritance#Implementations我尝试用以下编程语言编写代码(我还包括最新的尚未发布的1.0版本(2013)语言,如Kotlin,Ceylon):

  • C ++ 几乎可以,但无法解决撰写的变量的重载函数
  • Scala 编译错误:trait继承了两次;即使被间接继承欺骗,它仍会产生错误;另见other guy's question about multiple generic mixin inheritance in Scala
  • Eiffel 编译错误:无函数重载
  • Ceylon 特征不能有变量(也没有受保护的成员,因此没有技巧可以在派生类中存储数据,锡兰的特征也没用)
  • Fantom no generics / templates
  • Kotlin 编译错误:超类型出现两次;委托看起来很独特,但它没用,因为既不能访问受保护的成员,也不能访问委派给
  • 的变量
  • Rust 没有函数重载;特征不能存储数据; traits不能定义方法(带有body) - 正在处理的问题;
  • OCaml 编译错误:没有函数重载;它也没有检查我的函数的参数类型,所以它是如何“静态打字”的?!
  • 卷曲编译错误:没有函数重载;它也不会检查函数体,除非它被调用,所以它是如何“静态类型”的呢?是根据它编译还是解释?!
  • Gosu 是一个糟糕的笑话,根本不可用:无法使用一个mathod编写和实现简单的接口(错误:ClassFormatError:非法字段修饰符)。谁真的使用这种语言?!

顺便说一下:当我尝试将Java支持监听器放入单独的类时,我想到了这个问题(在许多类中有:List&lt; ListenerType&gt; ... addListener(...)... removeListener(。 ..))

C ++ 几乎有效:

template <typename T>
class Template { public: void function(T i) {} };
class Composed : public Template<int>, public Template<double> { };

Composed composed;
composed.Template<int>::function(3); //i want: composed.function(3);
((Template<double>&)composed).function(2.5); //i want: composed.function(2.5);

编辑:在C ++中,问题是继承功能隐藏。也可以看看 Function with same name but different signature in derived classWhy does an overridden function in the derived class hide other overloads of the base class?

编辑2:在C ++中,使用模板和部分特化,有可能使用肮脏的技巧来简化特征的使用:

#include <iostream>
#include <typeinfo>

class Void { };
template <class A, class B> class CleverTrait;
template <class A, class B> class CleverTrait;
template <class A> class CleverTrait<A, Void>
{
public:
    void function(A arg) { std::cout << "Hello for type " << typeid(A).name() << std::endl; }
};
template <class A, class B> class CleverTrait<A, CleverTrait<B, Void> > : public CleverTrait<B, Void>
{
public:
    using CleverTrait<B, Void>::function;
    void function(A arg) { std::cout << "Hello for type " << typeid(A).name() << std::endl; }
};

class ComposedByClever : public CleverTrait<double, CleverTrait<int, Void> > { };

int main()
{
    ComposedByClever composedByClever;
    composedByClever.function(5);
    composedByClever.function(2.3);
    return 0;
}

这意味着 C ++中的这个特定示例,但是如果不相关的traits共享函数名,则无法在C ++中继承和使用所有函数。

编辑3:我还应该检查支持mixins的任何编程语言:http://en.wikipedia.org/wiki/Mixins#Programming_languages_that_use_mixins

  • D 有效,但只能通过字符串操作mixin,因此重构在这种情况下会被破坏mixin(GenerateSomething!("IfClassNameHereManualRenaming"));

编辑4:添加了“Gosu”语言评论。

编辑5:Gosu编程语言有更新0.10.2,它修复了接口被破坏的问题。然而,尽管他们声称已经通过了仿制药和授权,但代表团+具体化的仿制药并不起作用。

1 个答案:

答案 0 :(得分:2)

C ++:类似于CRTP(see comment to OP)这个奇怪的想法我的意思更像是:

#include <typeinfo>
#include <iostream>

struct Dummy
{
private:
  // dummy type to prevent overload resolution from ever choosing this overload
    struct ParamDummy { explicit ParamDummy(); };
public:
    void function(ParamDummy);
};

template<typename T, typename Base = Dummy>
struct Template
    : Base
{
    using Base::function;
    void function(T i) { std::cout << typeid(T).name() << std::endl; }
};

struct SecondBaseClass
{
    void function2() { std::cout << "function2" << std::endl; }
};

struct Composed
    : Template<int, Template<double>>, SecondBaseClass
{};

int main()
{
    Composed c;
    c.function(5.0);
    c.function(5);
    c.function2();
}

对于Template中的每个不同成员函数名称,您需要一个using指令。因此,该数字仅取决于当前类中的成员函数的数量,而不取决于基类。

在某些方面与多重继承不同,但它允许简单的函数重载。

如果基类只共享某些而不是所有成员函数,那就太棘手了。