V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
huzhikuizainali
V2EX  ›  C#

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

  •  
  •   huzhikuizainali · 200 天前 · 655 次点击
    这是一个创建于 200 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题简述:书中说数组排序可以使用 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 方法呢?

    Nooooobycat
        1
    Nooooobycat  
       200 天前
    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
        2
    Nooooobycat  
       200 天前
    5. 难道 BCL 中就没有自己的 CompareTo ?
    答:你觉得 c#的开发者,何德何能能够知道你的这个类怎么排序? 用什么字段排序? 根本不可能的嘛,他又不会算命,所以肯定是你根据你业务逻辑的需求进行排序!

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

    继承是一种代码组合方式,告诉外部使用者,这个东西不单可以做某个事情,并且这个事情是像以前(父类)那么做的。
    huzhikuizainali
        4
    huzhikuizainali  
    OP
       199 天前
    @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
        5
    Nooooobycat  
       199 天前 via iPhone
    1. 那个是强制转换类型的语法。因为 compareTo 入参数是 Object 类,不是 Myclass ,所以要做一下类型转换。如果你传入的不是 MyClass ,就会报错

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


    @huzhikuizainali
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2870 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 06:59 · PVG 14:59 · LAX 23:59 · JFK 02:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.