既然已经继承了 BCL 中的 IComparable 接口,为什么还要自己写 CompareTo 方法的实现?

211 天前
 huzhikuizainali

问题简述:书中说数组排序可以使用 Array.Sort 方法。但是如果你自己写了一个类 Myclass ,然后实例化一个 Myclass 类型的数组,就没有办法使用 sort 方法排序,因为 Array 类的 Sort 方法其实依赖千一个叫作 IComparable 的接口,它声明在 BCL 中,包含唯一的方法 CompareTo 。IComparable 接口的声明。注意,接口主体内包含 CompareTo 方法的声明,指定了它接受一个 object 类型的参数。尽管该方法具有名称、参数和返回类型,却没有实现。尽管在接口声明中没有为 CompareTo 方法提供实现,但 IComparable 接口的 NET 文档中描述 了该方法应该做的事情,你可以在创建实现该接口的类或结构时参考。文档中写道,在调用 CompareTo 方法时,它应该返回以下几个值之一:

1 、负数值如果当前对象小于参数对象;

2 、正数值如果当前对象大于参数对象;

3 、零如果两个对象在比较时相等。

Sort 使用的算法依赖于使用元素的 CompareTo 方法来决定两个元素的次序。int 类型实现了 IComparable, 但是 MyClass 没有,因此当 Sort 尝试调用 MyClass 不存在的 CompareTo 方法时会抛出异常。

---------太好了,只要我的 Myclass 继承了 IComparable 接口。就可以愉快的使用 sort 方法了吧?可是看到下面代码的时候我就沉默了。你看第三行,它怎么自己实现了 CompareTo 方法。难道我继承了 IComparable 接口不就是不想重复造轮子么?如果我自己重写 CompareTo ,那还不如不继承接口,自己直接手写 sort 方法不就完了? 难道 BCL 中就没有自己的 CompareTo ?如果没有自带的 CompareTo ,那么当你对标准数组排序调用 sort 方法时,sort 调用的是谁的 CompareTo 方法呢?

679 次点击
所在节点    C#
5 条回复
Nooooobycat
211 天前
1. 根本原因是你没理解面向对象

2. 可是看到下面代码的时候我就沉默了。你看第三行,它怎么自己实现了 CompareTo 方法
回答:一个类如果声明要实现( implements )一个接口,则必须对接口里所有的抽象方法进行实现,给出具体的逻辑。否则会发生编译错误

3. 难道我继承了 IComparable 接口不就是不想重复造轮子么?如果我自己重写 CompareTo ,那还不如不继承接口,自己直接手写 sort 方法不就完了?
回答:那你再想想,为啥你继承了这个接口,就自动获取了那个能力? 假设都有一个 Closeable 接口,MyClass 继承了它,为啥会自动获取 close 的逻辑?
不可能呀,肯定是你要自己写代码实现呀! 问题来了,为什么要用接口呢?

4. 为什么要用接口?
回答:一个具体的例子,假设你的程序要在关闭时释放所有资源(比如文件句柄、数据库连接等),那么你只需要写一个函数就能实现,但具体这个资源的释放
逻辑是怎么实现的,你不用管,你只需要知道,实现了 Closeable 接口的那些类都可以调用 close 方法,一般都拿来释放资源(文件句柄、数据库连接):

func CloseAll(List<Closeable> c) {
c.foreach(c -> c.close)
}

同理,对一组数组进行排序,不确定的是什么? 是数组里元素次序怎么确定,就是你这个 MyClass 的实例之间如何比较大小的问题。 这个是你需要去指定的。
Nooooobycat
211 天前
5. 难道 BCL 中就没有自己的 CompareTo ?
答:你觉得 c#的开发者,何德何能能够知道你的这个类怎么排序? 用什么字段排序? 根本不可能的嘛,他又不会算命,所以肯定是你根据你业务逻辑的需求进行排序!

6. 如果没有自带的 CompareTo ,那么当你对标准数组排序调用 sort 方法时,sort 调用的是谁的 CompareTo 方法呢?
答:就 Java 来说,常见的类如 Integer 、Double 都实现了这个方法,所以可以对 List<Integer>进行排序。
nebkad
211 天前
接口(interface) 是一种调用约定,告诉外部使用者,这个东西可以做某个事情。
所以,我们通常会说“实现一个接口”而不是“继承一个接口”。

继承是一种代码组合方式,告诉外部使用者,这个东西不单可以做某个事情,并且这个事情是像以前(父类)那么做的。
huzhikuizainali
211 天前
@Nooooobycat 谢谢回复。
我在研究你的回复时,发现有几个问题我没有搞懂。
1 、截图中 CompareTo 模块中 MyClass me=(MyClass)obj;是什么意思?实例化一个 MyClass 对象。我过去看到的都是 MyClass me=new MyClass();

2 、if(this.TheValue<mc.TheValue) return -1; this 在这里指哪个对象?(书中说:this 关键字在类中使用,是对当前实例的引用。用途之一用于区分类的成员和局部变量或参数;----具体到这个模块谁是“当前实例?” public int TheValue; 这句可没有给出初始值。那么 this.TheValue 的值是多少呢?)
Nooooobycat
211 天前
1. 那个是强制转换类型的语法。因为 compareTo 入参数是 Object 类,不是 Myclass ,所以要做一下类型转换。如果你传入的不是 MyClass ,就会报错

2. 这个我不打算回答你,原因是你根本就不理解面向对象。 书里关于这一部分的好好看一下就清楚了


@huzhikuizainali

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/980459

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX