Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/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
Inheritance 如果汽车是汽车的一个子类型,为什么汽车->;void被认为是Car的一个子类型->;无效的_Inheritance_Functional Programming_Language Agnostic_Covariance_Contravariance - Fatal编程技术网

Inheritance 如果汽车是汽车的一个子类型,为什么汽车->;void被认为是Car的一个子类型->;无效的

Inheritance 如果汽车是汽车的一个子类型,为什么汽车->;void被认为是Car的一个子类型->;无效的,inheritance,functional-programming,language-agnostic,covariance,contravariance,Inheritance,Functional Programming,Language Agnostic,Covariance,Contravariance,在阅读有关继承的文章时,我无法理解下面的推理。显然,这是正确的,因为逆变确实起作用,我只想理解其中的道理。 首先,它表明: 如果函数返回车辆,则它是返回车辆的函数的子类型。这是因为所有的车辆都是汽车。(返回类型的协方差) 如果功能采用车辆,则它是采用车辆的功能的子类型,因为“一般而言,车辆上的每个功能都是 汽车。” 我无法理解这种倒置的解释,因此我在下面展示: 我天真的诠释: 由于所有车辆上的功能都适用于所有车辆,因此功能执行车辆是功能执行车辆的一个子类型,因为车辆的功能集较小-车辆可以具

在阅读有关继承的文章时,我无法理解下面的推理。显然,这是正确的,因为逆变确实起作用,我只想理解其中的道理。 首先,它表明:

  • 如果函数返回车辆,则它是返回车辆的函数的子类型。这是因为所有的车辆都是汽车。(返回类型的协方差)
  • 如果功能采用车辆,则它是采用车辆的功能的子类型,因为“一般而言,车辆上的每个功能都是 汽车。”
    我无法理解这种倒置的解释,因此我在下面展示:
我天真的诠释:


由于所有车辆上的功能都适用于所有车辆,因此功能执行车辆是功能执行车辆的一个子类型,因为车辆的功能集较小-车辆可以具有更多功能。

您的问题是关于功能的协方差和逆变,我认为如果我们把论文中的一些语言不可知的符号关系映射到实际的代码中,这将有助于你的理解。在C++中,这里讨论的函数是:

int GetSpeedOf(Vehicle vehicle);
必须从以下方面理解子类型:;如果一个函数需要任何类型的动物,你可以给它一只猫,一切都应该正常,但事实并非如此;需要猫的功能不能在任何类型的动物身上工作

假设您理解可以将Car传递给GetSpeedOf函数,那么现在我们将讨论函数接受函数的更复杂情况,这会在图片中引入矛盾

下面的CarWrapper有一辆私家车,它将使用外部提供的功能对其执行操作。该功能必须适用于汽车。所以,如果你给出一个更适用于所有车辆的函数,那就好了

#include <functional>

class Vehicle { };
class Car : public Vehicle { };

class CarWrapper
{
    Car car;
    typedef std::function<auto(Car) -> void> CarCallback;
    CarCallback functionPtr;

public:
    void PassCallback(CarCallback cb)
    {
        functionPtr = cb;
    }

    void DoStuff()
    {
        functionPtr(car);
    }
};

void Works(Vehicle v){}

int main() {
    CarWrapper b;
    b.PassCallback(&Works);
}
这意味着,如果我们期望有一个汽车工厂,当我们得到一个汽车工厂时,我们应该感到满意:

#include <functional>

class Vehicle { };
class Car : public Vehicle { };

typedef std::function<auto() -> Vehicle> VehicleFactory;
typedef std::function<auto() -> VehicleFactory> VehicleFactoryFactory;
typedef std::function<auto() -> VehicleFactoryFactory> VehicleFactoryFactoryFactory;

void GiveMeAFactory(VehicleFactoryFactoryFactory factory)
{
    Vehicle theVehicle = factory()()();
}

typedef std::function<auto() -> Car> CarFactory;
typedef std::function<auto() -> CarFactory> CarFactoryFactory;
typedef std::function<auto() -> CarFactoryFactory> CarFactoryFactoryFactory;

Car ActualCarCreateFunc() { return Car(); }
CarFactory CarFactoryCreateFunc() { return &ActualCarCreateFunc; }
CarFactoryFactory CarFactoryFactoryCreateFunc() { return &CarFactoryCreateFunc; }

int main() {
    GiveMeAFactory(&CarFactoryFactoryCreateFunc);
}

在逆变的情况下,很难用直观的术语来理解这一点。这就是为什么我的CarWrapper只尝试为规则的一个应用解释它,而CarFactory示例包含三个协方差应用。

所有汽车都是汽车,但不是所有汽车都是汽车(C谢谢,它确实帮助了我,但如果您能详细说明Void(汽车)作为Void子类型的那部分,我将不胜感激(汽车)。最理想的是用简单的术语,如我原来问题下的评论。我认为你的最后一段中有错误-Car->Void不是车辆的子类型->Void。正确;我必须在纸上画出来,看看多个对冲应用程序应该如何工作。希望现在我在多行上都有它。我还添加了一点在第一个代码示例之后,请使用更通俗的英语。如果您想一想这些函数将包含哪些内容,希望您能够理解为什么当PassCallback的签名请求实际在汽车上运行的函数时,Works函数是有效的。非常感谢。我添加了我自己的答案(正如我的一位同事用简单的语言向我解释的那样)但我当然会留下你的答案,因为它提供了很多细节和实现示例。
#include <functional>

class Vehicle { };
class Car : public Vehicle { };

typedef std::function<auto() -> Vehicle> VehicleFactory;
typedef std::function<auto() -> VehicleFactory> VehicleFactoryFactory;
typedef std::function<auto() -> VehicleFactoryFactory> VehicleFactoryFactoryFactory;

void GiveMeAFactory(VehicleFactoryFactoryFactory factory)
{
    Vehicle theVehicle = factory()()();
}

typedef std::function<auto() -> Car> CarFactory;
typedef std::function<auto() -> CarFactory> CarFactoryFactory;
typedef std::function<auto() -> CarFactoryFactory> CarFactoryFactoryFactory;

Car ActualCarCreateFunc() { return Car(); }
CarFactory CarFactoryCreateFunc() { return &ActualCarCreateFunc; }
CarFactoryFactory CarFactoryFactoryCreateFunc() { return &CarFactoryCreateFunc; }

int main() {
    GiveMeAFactory(&CarFactoryFactoryCreateFunc);
}
Car is a subtype of Vehicle means that:
(Vehicle -> void) is a subtype of (Car -> void)
((Car -> void) -> void) is a subtype of ((Vehicle -> void) -> void)
(((Vehicle -> void) -> void) -> void) is a subtype of (((Car -> void) -> void) -> void)