留言

留言区

留言》上有48条评论

  1. 蒋鸿雁

    最近休假了,才看到邮件,祝福未来的日子更好!

    回复
    1. hongjiang 文章作者

      核心作者的blog:http://www.chuusai.com/,他们也有个邮件列表,在项目主页可以找到:https://github.com/milessabin/shapeless

      回复
  2. 蓝川

    我在gfw的wb下面看到你的博客
    想问个问题
    我在国外,访问www.nicovideo.jp 的时候浏览器会去访问www.x-yao.com,我已经把hosts清空了,也还是不行。但是访问不是www开头的其它页面就没问题,请问到底是怎么回事?ping也ping不过去,全部timeout

    回复
    1. hongjiang 文章作者

      我这边访问没有这个问题,你那边可能是 http://www.nicovideo.jp 这个域名被劫持到了www.x-yao.com,你ping的时候这两个网址是否显示同一个ip?尝试刷新一下dns看看:http://cnzhx.net/blog/how-to-flush-dns-cache-in-linux-windows-mac/

      回复
        1. 蓝川

          之前一直想办法,有ip对但是ping不通的时候,现在ip又错了,可以ping通。是这个ip 106.186.22.71

          回复
        2. 蓝川

          啊,我弄好了。原来是小红伞不让我写入hosts,所以每次保存都另存成了txt,关了以后改了权限就写好了。解决!谢谢

          回复
  3. TonyGong

    hongjiang, 你好!
    关于里氏替换原则的疑惑,求解答:(子类重载父类的方法,需要提供比父类更宽松的参数类型)
    下面是根据里氏替换原则的例子:
    // 作为参数类型使用
    class Parent
    class Child extends Parent
    class GrandChild extends Child

    class Father {
    def func(map: Child) = {
    println(“执行父类…”)
    }
    }

    class Son extends Father {
    def func(map: Parent) = { // 根据里氏替换原则,子类重载父类的方法,需要提供比父类更宽松的参数类型
    println(“执行子类…”)
    }
    }

    object Client extends App {
    val p: Father = new Son
    p.func(new Parent) // 编译出错,type mismatch, expected: Child, actual: Parent
    // 因为p是Father类型的实例,并没有`def func(map: Parent)`方法,所以出错
    p.func(new Child) // 调用了Father类中的`def func(map: Child)`方法,当然可以

    val s: Son = new Son
    s.func(new Parent) // 调用了Son类中的`def func(map: Parent)`方法,当然可以
    s.func(new Child) // 编译出错,ambiguous reference to overloaded definition, both method func in class Son of type (map: Parent)Unit
    // and method func in class Father of type (map: Child)Unit match argument types (Child)
    // 原因是因为s中通过继承父类后存在有`def func(map: Parent)`和`def func(map: Child)`两个方法,
    // s.func(new Child)这种方式调用时,这两个方法都满足,所以编译器不知道到底调用哪一个,就报ambiguous reference to overloaded definition错误
    }

    如果破坏了这个规则:子类重载父类的方法,需要提供比父类更宽松的参数类型

    class Father {
    def func(map: Parent) = {
    println(“执行父类…”)
    }
    }

    class Son extends Father {
    def func(map: Child) = { // 根据里氏替换原则,子类重载父类的方法,提供的参数类型范围比父类的更小
    println(“执行子类…”)
    }
    }

    object Client extends App {
    val p: Father = new Son
    p.func(new Parent) // 编译通过
    p.func(new Child) // 编译通过

    val s: Son = new Son
    s.func(new Parent) // 编译通过
    s.func(new Child) // 编译通过
    }

    居然编译全部通过了。并且s.func(new Child) 的情况,照理说,子类也照样拥有两个方法:`def func(map: Parent)`和`def func(map: Child)`,为什么这个时候,编译的时候,没有报ambiguous reference to overloaded definition错误呢?
    希望能给予回答。谢谢!

    回复
    1. hongjiang 文章作者

      你这里的Father和Son里的func并不存在 override 关系,只是子类里定义了一个同名但不同参数的func函数,是overload 不是 override

      回复
      1. hongjiang 文章作者

        可能你把好几个感念混淆了,
        1)对象的默认继承关系是“不变”的,而不是“协变”或“逆变”的;要额外显式声明才行。
        2)java/scala里一个方法是由方法名和参数个数/参数类型确定的,参数个数不同或类型不同的话是不同的方法。
        3)函数类型是逆变的,但你的例子不是函数类型

        回复
      2. TonyGong

        hongjiang,你好,谢谢你的回答。

        这里的Father和Son确实就是为了模拟一下里氏替换原则。是重载overload,而非重写override。
        我的困惑是,里氏替换原则为什么要求子类重载父类的方法时,要求方法的参数要比父类的参数类型更宽。
        难道比父类的参数类型窄了。就不能替换父类了么?子类继承自父类,肯定拥有了父类的方法。然后重载一个参数类型更窄的方法时,只是在父类的基础上多了一个属于子类自己的方法而已。这样的话,子类也是照样可以代替父类的,也没有违背里氏替换原则。

        既然没有违背,为什么有子类重载父类的方法时,要求比父类方法参数更宽的类型这个限制呢?
        求解释。

        回复
        1. hongjiang 文章作者

          overload 是表示同名不同参的方法,跟里氏替代没有任何关系。里氏替代是子类(实现)可以替代父类(接口),行为的替代是通过override体现的。

          回复
        2. lcn

          不明白你描述的LSP具体是在讨论什么,感觉这里混淆的地方可能是在于形参类型(formal parameter types)和参数类型(type parameters)的区别,参见

          Let A1, …, An be the type parameters of M and let B1, …, Bn be the type parameters of N. After renaming each occurrence of a Bi in N’s type to Ai, the bounds of corresponding type variables are the same, and the formal parameter types of M and N are the same.

          回复
          1. lcn

            引用地址没显示:http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.2

  4. 职位推荐

    王先生您好,我是猎头nick,不好意思打扰了。
    华为正在招聘高端职位,您是他们寻找的候选人之一,请问方便联系吗?期待您的回复。我邮箱是nick.cai@dsi.com.cn。

    回复
  5. kmxz

    请问《Functional Programming in Scala》中文版什么时候才可以买到呢?
    谢谢老师!

    回复
    1. hongjiang 文章作者

      内容翻译已经完成,现在在第二次矫正中。但后续流程我不知道要多久。

      回复
  6. Hank

    您好,本人在美国就读计算机类研究生,最近在上Scala有关的课程,从知乎上找到了您的博客,很多东西写的非常好,本人想做一些文章翻译然后用于与教授同学共享讨论,也可能会发在我自己的博客上,不知道您是否愿意授权于我去做这样的事情。

    回复
    1. hongjiang 文章作者

      没有问题,如果发现错误或问题也欢迎指出。

      回复
  7. feng

    hongjiang,您好:

    看了《scala在挖财的实践》不由得要竖大拇指,后来想起来一个问题想请教下:akka这部分,当因为数据量越来越大,需要类似集群那样来扩展时,你们在akka这块具体怎么弄的呢?因为听你演讲说没有用akka的集群,所以对这个感到奇怪,特地请教!

    希望能适当深入、具体点,谢谢!

    回复
    1. hongjiang 文章作者

      你说的扩展性问题,并不一定要用集群来解决。因为akka的actor本身就支持remote actor,所以当把角色定义清楚,让这些actor之间远程通讯就可以了。集群相对复杂,它除了解决扩展性还解决高可用的问题,在不是非常必要的情况下可以不用引入集群。

      回复
      1. feng

        谢谢hongjiang,最近在调研akka,想到了这个问题,打算实际验证下,有没有相关好资料推荐下,谢谢!

        回复
        1. hongjiang 文章作者

          最好的是官方的文档,可以下载pdf打印成书,也可以搜一下akka相关的书籍,但书籍的版本未必跟得上,要注意。

          回复
          1. feng

            hongjiang,您好:
            官方remote的例子我搞清楚了,但是之后想起来实际的工程应用时,心里还是有疑问,特在此请教:
            以金融行业计息的例子为例,有两个问题:
            1、假如待处理的数据越来越多,一个机器上的actor实例怎么自动扩展来处理越来越多的数据呢?
            2、在超出一台机器处理能力范围之外的数据,创建remote actor的时候,url中包含了远程机器的ip、端口号之类的信息,这样看来扩展时需要技术人员设计、开发等方式的介入,想请教在这样的情况下,有没有什么办法能够自动弹性支撑数据量的扩充呢?

            谢谢!

          2. feng

            不好意思,hongjiang:
            还有个问题,很多数据要处理的情况下,为了保证不遗漏,是不是要在一个地方把数据分片后通知到各个负责处理数据的actor,或者由这些actor从一个地方集中获取每个actor处理的数据的范围?
            有没有更好的办法?
            谢谢!

  8. feng

    谢谢hongjiang,
    找到了一个官方的demo,打算好好分析下。回头可能会整理个分析文档。

    回复
  9. 您好,我们做培训的,想请您给我们客户做scala-spark方面的培训,您要是有兴趣可以联系我。

    回复
  10. viyond

    想看看pandora相关的设计思想或者代码,不知道哪里可以找到代码,非常感谢。

    回复
    1. hongjiang 文章作者

      Pandora没有开源,你可以关注一下java9里的模块化。

      回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注