【问题标题】:why can we declare delegates outside a class? Is it not against OOP concept?为什么我们可以在类之外声明委托?不是反对OOP概念吗?
【发布时间】:2011-09-05 13:36:22
【问题描述】:

根据 oops Fundamentels,所有内容都必须在一个类中。那为什么我们可以在类之外创建委托呢?

【问题讨论】:

  • @Mehrdad - 认为他只是指 OOP。

标签: c# oop


【解决方案1】:

首先,您关于什么是 OOP“基础”的想法并不是基础。 “面向对象”一词的发明者艾伦凯有句名言:

我创造了“面向对象”这个术语,我可以告诉你我并没有想到 C++。

当然,词汇上“一切都在一个类中”的想法不是 OOP 的基本原则。我什至不清楚“类”的概念是面向对象编程的基础。 “基于类的继承”模式只是嵌入到对消息传递、数据抽象和实现共享等概念的语言支持的一种方式。

其次,您暗示 C# 语言设计者正试图制作一种符合 OOP 的“基本原理”的语言,这是本末倒置。相反,我们希望创建一种语言,支持大型、多样化的团队在我们的平台上共同开发可版本化、独立、交互的软件组件。 OOP 恰好是实现这一目标的好方法,所以这就是我们正在做的事情。

我们当然不会以任何方式尝试制作“纯”OOP 语言。如果它们支持真实世界的客户受益场景,我们将从任何范例中获取想法。 C# 中的一些想法取自 OOP、过程式编程、函数式编程、动态语言等等。

第三,你的问题在逻辑上是不一致的。你问为什么你可以在一个类之外定义一个委托。但是委托是一个类。代表是一个非常特殊的类;它始终是密封的,它始终从 System.MulticastDelegate 继承,并且始终具有相同的成员。但它是一个类。我们给它特殊的语法来表明它是一种非常特殊的类。能够在类之外定义委托类是有意义的。

第四,将委托放在类之外是合法的最终原因是因为这样做非常方便。你认为Func<T>EventHandler 应该进入什么类?那堂课会是“OOP”吗?根据传统的“OOP”智慧,一个类应该通过将操作数据相关联表示一个概念;你提议的Func<T>父类代表什么概念类的东西,它上面的操作和数据是什么?

不存在这种合理的外部类,也没有与Func<T>的“外部类”相关的操作或数据。那么为什么要强制用户定义一个无用的外部类,只是为了符合某人对“OOP”含义的错误理解?

【讨论】:

  • @Eric- 你怎么能说类的概念不是编程的基础?每本书和网站都提到类是 oop 的基础。
  • @vatspoo:你能发明一种没有类的面向对象语言吗?你能用一种没有类的语言以面向对象的风格进行编程吗?是的,是的。完全可以在 Scheme、JavaScript 或 C 中以 OO 风格进行编程,尽管事实上它们都没有类。
  • @Oscar:这个问题对于 600 个字符来说太宽泛了。但是你可以在 C++ 中做的任何事情都可以在 C 中做,只是有点难看。例如,假设我想在 C 中具有“所有对象都可以转换为基本对象类型”的概念。COM 对象以 IUnknown 接口的形式具有该概念,并且在C. 请记住,COM 是对象的二进制标准;它所说的只是事物在内存中的布局方式,而不是调用代码的编程语言文本的样子。
  • @vatspoo:作为一个快速的例外:Javascript 是基于原型的。它仍然是 OOP,但类永远不会混入其中。 (事实上​​,这是另一种“大”的 OOP)
【解决方案2】:

实际上委托是一种类型(类)。当你声明一个委托type

时,它只是一个语法糖,如果可以的话
public delegate int PerformCalculation(int x, int y);

委托是一种安全的类型 封装了一个方法。 委托类型派生自 .NET Framework 中的 Delegate 类。

http://msdn.microsoft.com/en-us/library/ms173172%28v=vs.80%29.aspx

所以当你在一个类之外声明一个委托时,你实际上是在创建一个新的类型/类。然后在一个类中创建一个委托实例

话虽如此,就像@Mehrdad 出色地指出的那样,一切都必须在一个类中并不是 OOP 的要求。

【讨论】:

  • 例如,我们可以提到委托不属于某个类。也许这是对问题作者的困惑以及提出问题的原因。这就像一个类声明。
  • 但是数组也是一种类型。为什么我们不能在外面声明呢?
  • @vatspoo - 当你在一个类之外声明一个委托时,你实际上是在创建一个新的类型/类。您创建数组的一个实例。你不是真的在创建一种新类型的数组吗?
  • @manojlds- 关于结构?它们是值类型,我们可以在类之外声明它们。
【解决方案3】:

不是 OOP“基础”。

这恰好是 Java 等某些语言中的一种语言选择。

面向对象的编程仅仅意味着使用称为“对象”的实体对问题进行建模,这些实体具有状态行为。它没有说明你的代码应该去哪里。

事实上,你甚至可以在没有类的情况下创建“对象”。只要返回一个有闭包的委托,你就有了一个对象。

例子:

//An "adder" that adds the value you give it to its current value
Converter<int, int> MakeAdder(int addend) //"constructor"
{
    return msg =>
    {
        addend += msg;
        return addend;
    };
}

//...
var adder = MakeAdder(100); //Now I have an adder object!
for (int i = 0; i < 10; i++)
    Console.WriteLine(adder(i));

C# 中的 lambda 是一个类,这完全不是重点。你可以在像 Scheme 这样的语言中做这样的事情,其中​​根本不存在“类”或“对象”之类的东西,只有 lambdas。

【讨论】:

  • 谢谢...帮我省了打字和血压的问题!顺便说一句,我最喜欢的真实示例是 Linux 上的 GTK+/GNOME 代码。完全 OO 编程风格,用 C 语言完成。
  • @Harper:Windows 也一样! Windows 是传递消息/参数的对象。 :)
【解决方案4】:

C# 是一种多范式语言,而不是纯粹的面向对象语言。

【讨论】:

  • 正确,但没有回答问题。
  • 如果问题是“为什么我们允许在 C# 中的类之外创建委托,尽管这违反了 OOP(假设确实如此)?”我的意思是“因为 C# 允许,C# 不一定是纯 OOP”
【解决方案5】:

我之前也想过这个问题,但后来我明白了直接在命名空间内声明它的原因。这是因为当你声明一个委托时,会在后台为该委托创建一个巨大的类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-22
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 1970-01-01
    • 2020-02-25
    相关资源
    最近更新 更多