Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 如何强制只调用超类';s方法,尽管它们已被重写(在Ocaml中)_Oop_Ocaml_Overriding_Late Binding - Fatal编程技术网

Oop 如何强制只调用超类';s方法,尽管它们已被重写(在Ocaml中)

Oop 如何强制只调用超类';s方法,尽管它们已被重写(在Ocaml中),oop,ocaml,overriding,late-binding,Oop,Ocaml,Overriding,Late Binding,老实说,我不太了解OCaml的对象系统。以下代码片段说明了我的问题: class foo = object (o) method foo1 y = print_endline "foo1"; o#foo2 (y - 1) method foo2 y = print_endline "foo2"; if y > 0 then o#foo2 y else print_endline "end" end class b

老实说,我不太了解OCaml的对象系统。以下代码片段说明了我的问题:

class foo =
  object (o)

    method foo1 y =
      print_endline "foo1";
      o#foo2 (y - 1)

    method foo2 y =
      print_endline "foo2";
      if y > 0 then o#foo2 y else print_endline "end"
  end

class bar =
  object (o : 'self_type)
    inherit foo as super

    method foo2 y =
    print_endline "bar2";
    if y > 0 then super#foo1 y else print_endline "endbar"

  end

let _ = (new bar)#foo2 3
执行时,代码段将生成以下输出:

bar2
foo1
bar2
foo1
bar2
endbar
,显示超类方法foo1(通过super#foo1调用)从子类执行重写的方法foo2。相反,我希望它从超类调用方法foo2,因为它是通过super调用的


是否有可能实现这种行为,即让一个超类方法只调用其他超类方法,即使它们在子类中被重写?

对此我不是100%确定,但我很确定您不能。在OCaml中,继承和子类型是两个不同的概念。类可以是另一种类型的子类型,而不需要继承。继承所做的一切就是从继承的类中拉入方法

多态是通过结构类型实现的,所以您对 FoO2 Bar < /C>中的方法,因为 Bar < /C> >实现了 FoO2,并不是因为<代码> Bar <代码>继承了<代码> Foo(如“C++”,其中“代码> bar FuoO2由于虚拟函数表查找而被调用”)

也就是说,OCaml确实提供了一种使用
inherit…as…
语法区分重写方法和继承方法的方法。在您的示例中的
bar
中,
o#foo1
super#foo1
是相同的方法(因为
bar
不实现
foo1
),而
o#foo2
super#foo2
是不同的方法。尽管如此,我认为继承的类无论如何都无法知道它已被继承,也无法区分它的方法和被重写的方法。这可能有一些语法,但我非常怀疑,因为继承和多态性是独立的概念。

不,不是。这是“后期绑定”,是OO的一个基本概念,不是OCaml特有的


我不知道你想做什么,但面向对象编程可能不是正确的工具,或者至少不是那样使用的。如果你想学习OCaml,你可能应该专注于非面向对象的部分,这对于一开始来说已经足够有趣了。

我想说,如果你想硬编码这种行为,最好不要使用面向对象编程。只需将其实现为调用其他函数的函数

(“我所理解的那种行为:如果从被称为
super#foo1
的代码内部调用
foo2
,那么应该调用超类实现中的
foo2
,而不是子类中更“具体”的实现)

这是最简单、最干净、最清晰的处理方式:编写能满足您需求的函数

或者你应该向自己和我们解释:为什么你需要OOP?问题文本中没有给出原因。为什么要使用
foo1
foo2
方法而不是独立的函数?(除了
foo1
foo2
,您的程序中可能有一些对象、类和方法(如果适用)

想知道这个问题是否来自与其他语言的比较

如果你知道另一种面向对象语言,那么你想从OOP中得到“那个行为”是奇怪的:它不是java、C++中所期望的行为,因为它们使用了一个虚拟方法表的概念,它在运行时与每个对象相关联,因此在程序中调用方法时,它在运行时被调度到实际与对象关联的方法的实现中。因此,简言之:每当您在程序中使用方法调用表达式时,您都会遵循这个原则,即找到方法的实现(“后期绑定”),正如gasche所指出的那样。尽管仍然参考Niki Yoshiuchi指出的OCaml和使用虚拟方法表实现的语言之间的差异

将所有关于可用和想要的行为的讨论形式化 尽管在许多流行的OO语言中,您想要的可能不是预期的和可用的行为,但是如果您能够访问OOP实现内部,它是可以想象的,并且可以在某些特定的OOP系统中实现

比如说,如果在某些实现中,
super
是一个保存超类的方法表的结构(在解析当前对象的方法调用时要回退),并且这些方法是必须接收对象(方法表)作为第一个参数的函数,那么要执行您想要的操作,可以编写
super.foo1(超级,y)

(实际上,我想知道是否有OOP实现的内部结构向程序员公开,并且允许进行这样的调用。)

而在这个系统中,通常的OOP行为将通过
this.foo1(this,y)
来表示(其中
this
是当前对象的方法表)

您的OCaml调用
super#foo1y
或Java
super.foo1(y)
将此“我的”系统转换为
super.foo1(this,y)
(尽管仍然是Niki Yoshiuchi指出的OCaml与使用虚拟方法表实现的Java等语言之间的差异)

你可以看到这三种情况之间的区别

附录。寻找这样的语言 嗯,PHP可能是一种可以实现这种行为的语言,但是:

  • 仅在“类级”编程(静态方法),而不是对象级
  • 只有在函数调用时硬编码一些奇怪的代码时:
--它给出了你想要的行为:

$ ./a.out | head -10 bar2 foo1 foo2 foo2 foo2 foo2 foo2 foo2 foo2 foo2 $ 美元/年支出|总目-10 bar2 foo1 食物2 食物2 食物2 食物2 食物2 食物2 食物2 食物2 $ 即使在
Bar::foo2()
的代码中的函数调用中没有任何特殊的限定符,对fo也不感兴趣 $ ./test-force-super-binding.php | head -20 model2 foo1 model2 foo1 model2 foo1 model2 endmodel bar2 foo1 foo2 foo2 foo2 foo2 foo2 foo2 foo2 foo2 foo2 foo2 $

#include<iostream>

class Foo {
protected:
  static void foo1(int y) {
    std::cout << "foo1" << std::endl;
    foo2(y-1);
  }

public:
  static void foo2(int y) {
    std::cout << "foo2" << std::endl;
    if (y > 0)
      foo2(y);
    else
      std::cout << "end" << std::endl;
  }

};
  
class Bar: public Foo {
public:
  static void foo2(int y) {
    std::cout << "bar2" << std::endl;
    if (y > 0)
      foo1(y);
    else
      std::cout << "endbar" << std::endl;
  }
};

int main() {
  Bar::foo2(3);
  return 0;
}
$ ./a.out | head -10 bar2 foo1 foo2 foo2 foo2 foo2 foo2 foo2 foo2 foo2 $