【问题标题】:Object oriented code,in non-object oriented language [closed]面向对象的代码,以非面向对象的语言[关闭]
【发布时间】:2011-08-05 05:53:02
【问题描述】:

这个说法是真的吗??

编写面向对象的代码,即使是非面向对象的语言。

任何人都可以提供示例..或提供一些链接...

【问题讨论】:

  • 这句话在语法上不正确,所以它的真假没有实际意义。
  • 作为一个例子...查看 GTK 源代码或旧的 Xt 工具包。两者都是用 C 编写的。
  • 这个(非)问题更适合programmers.stackexchange.com

标签: java c++ c oop


【解决方案1】:

是的,你可以这样做,你可以用像 c 这样的过程语言来模拟像 继承多态 这样的 OOP 概念。

既然你要求一个代码示例,这里是一个:

要模拟继承,您只需要结构的第一个成员是超类的实例,然后您可以像 C++ 继承一样强制转换指向基类和派生类的指针。

struct BaseClass 
{     
   //... 
};  
struct DerivedClass 
{     
   struct BaseClass super;     
   //....  
};  

struct DerivedClass d; 
//UpCasting example  
struct BaseClass *base_ptr = (struct BaseClass *)&d; 
//Downclasting Example 
struct DerivedClass *derived_ptr = (struct DerivedClass *)base_ptr; 

当然,如果你真的需要 OOP,你应该使用 OOP 语言而不是这样玩。

【讨论】:

  • 你能找到任何包含代码的示例...或一些参考资料...??
  • 只要您的语言是图灵完备的,您就可以先在其中编写 Java 代码,然后再使用您的框架。当然,做到这一点的难易程度取决于具体的语言,但总是有可能的。
  • @Raihan Jamal:更新了答案以回答您的问题。
【解决方案2】:

即使使用非面向对象的语言(如 C),也很有可能编写面向对象的代码。以此为例:

typedef struct _Node {
    struct _Node* next;
    int data;
} Node;

// Constructor
Node* createNode() {
    return (Node*)malloc(sizeof(Node));
}

// Getter for data
int getNodeData(Node* node) {
    if(node != null) {
        return node->data;
    }
    return -1;
}

等等。当然,这确实需要程序员更加自律,但没有什么能阻止他以面向对象的方式表达他的代码。

【讨论】:

    【解决方案3】:

    考虑一下:面向对象的语言功能是如何实现的?通常,如果并非总是如此,则必须有一些面向对象特性的非面向对象实现:例如,在 C++ 中,向上转换/向下转换实际上是指针操作:如果我有一个从多个对象继承的对象,我将它的内存布置为所以:

    ->/**********************/
      / PARENT 1 FIELDS      /
      /**********************/
      / PARENT 2 FIELDS      /
      /**********************/
      / CHILD SPECIFIC FIELDS/
    

    -> 是一个指针:目前它指向对象的前面,所以从这里看,对象看起来像一个 CHILD,它继承自 PARENT1 和 PARENT2。如果我们将此对象强制转换为 PARENT2,我们只需要更改指针的位置:

        /**********************/
        / PARENT 1 FIELDS      /
     -> /**********************/
        / PARENT 2 FIELDS      /
        /**********************/
        / CHILD SPECIFIC FIELDS/
    

    这样从指针开始的内存布局看起来像一个 PARENT2 对象。

    类似的操作适用于大多数面向对象的操作。实现这一点所需的只是指针,而不是“面向对象”特性本身。所以,在这个实现下,如果你有指针,你可以自己创建面向对象。

    一个著名的例子是在 linux 内核中的实践。

    例如:container_of 宏定义为:

    #define container_of(ptr, type, member) ({ \
                    const typeof( ((type *)0)->member ) *__mptr = (ptr); 
                    (type *)( (char *)__mptr - offsetof(type,member) );})
    

    它只是简单地进行一些指针操作并强制转换为“向上转换”——获得一个父对象。

    【讨论】:

      【解决方案4】:

      也许最著名的例子是 GTk 库和衍生自它的 Gnome 桌面。

      这些都是用纯 C 编写的,但遵循纯 OO 设计原则。

      不难想象。

      C++:

      ret = object->method(parm1,parm2);
      

      带有笨重 OO 的 C:

      ret = method(Objectref,parm1,parm2);
      

      您可以使用这个和类似的习惯用法在 C 中实现任何 OO 设计。

      他们获得的是在 C++ 经历标准变化时的性能、兼容性和稳定性。

      您失去的是一些编译时验证的灵活性。您可以指定一个特定的方法需要一个“三角形”对象作为第一个参数,但您不能有一个方法可以采用一个必须接受任何参考值的通用“形状”对象。 另外,您需要多加注意。

      利弊有讨论here

      【讨论】:

        【解决方案5】:

        如果问题是“是否可以编写面向对象的代码,即使是在非面向对象的语言中”,那么答案是肯定的。 比如原来的C++编译器叫cfront,它把C++作为输入,输出C。所以可以用C来表达面向对象的代码,这绝对不是面向对象的语言。 但是,这样做很少有任何理由,而且有很多缺点,因为您无法从编译器那里获得帮助或支持。

        【讨论】:

        • 不只是编译器关心 OOP,你知道的。一种 OOP-lite(OO 减去对封装和继承的编译器支持)可能非常有用。考虑 ADT、GTK+ 等 API 甚至 Win32。当您可以将您传递的事物视为不透明的,并且只需使用一些定义明确的函数来修改它并查询它的状态时,这就是面向对象的。
        • 许多人会认为多态性(包括虚函数)对于面向对象的事物是必要的。您描述的工具很有用,但如果您真的想编写面向对象的代码,如果可以的话,使用面向对象的语言会容易得多。
        • 你的意思是,比如说,函数指针? Win32 的窗口过程(包括为了子类化窗口而改变它的能力)?等等?
        • 好吧,我想,不情愿地,您可能会声称某些 Win32 的东西有点面向对象。尽管如此,考虑到在 OO 语言和用 C 编写 Win32 API 调用之间的选择,我知道我会选择哪个。
        • 几乎所有的 Win32 在很大程度上都是面向对象的。你有一个 HDC,你可以在上面画画——不管你是在屏幕上画,还是在打印的页面上,甚至是生成一个元文件。您调用WaitForMultipleObjects,您不必关心这些句柄是否是针对进程、套接字、事件对象等的。可以通过向它们发送消息来操作控件,并处理许多标准消息。当然,C++ 可以使它更容易。但是在 C++ 中所有可能的事情在 C 中都是可能的,甚至可以很容易。所缺少的只是编译器的强制执行。
        最近更新 更多