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) // 编译通过
}
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.
祝福,离开阿里的路更宽广
谢谢老庄,保持联系。
感谢之前的之前的指点与帮助 祝一切顺利
保持联系。
祝福, 保持联系!
嗯,有机会回北京聚
宏江学长,祝福。 from 游骥
谢谢,保持联系
牛人,仰慕…祝福…希望有机会再聚…
有机会的
在路上,祝福宏江
多谢
最近休假了,才看到邮件,祝福未来的日子更好!
谢谢。
哪里有shapeless相关的文档啊?
核心作者的blog:http://www.chuusai.com/,他们也有个邮件列表,在项目主页可以找到:https://github.com/milessabin/shapeless
我在gfw的wb下面看到你的博客
想问个问题
我在国外,访问www.nicovideo.jp 的时候浏览器会去访问www.x-yao.com,我已经把hosts清空了,也还是不行。但是访问不是www开头的其它页面就没问题,请问到底是怎么回事?ping也ping不过去,全部timeout
我这边访问没有这个问题,你那边可能是 http://www.nicovideo.jp 这个域名被劫持到了www.x-yao.com,你ping的时候这两个网址是否显示同一个ip?尝试刷新一下dns看看:http://cnzhx.net/blog/how-to-flush-dns-cache-in-linux-windows-mac/
刷新过了,仍然不行。ping时它们是显示一个ip的。
之前一直想办法,有ip对但是ping不通的时候,现在ip又错了,可以ping通。是这个ip 106.186.22.71
啊,我弄好了。原来是小红伞不让我写入hosts,所以每次保存都另存成了txt,关了以后改了权限就写好了。解决!谢谢
遗憾,离开了!
你好,你的邮箱是什么,咱们通过邮件谈谈
邮件你了
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错误呢?
希望能给予回答。谢谢!
你这里的Father和Son里的func并不存在 override 关系,只是子类里定义了一个同名但不同参数的func函数,是overload 不是 override
可能你把好几个感念混淆了,
1)对象的默认继承关系是“不变”的,而不是“协变”或“逆变”的;要额外显式声明才行。
2)java/scala里一个方法是由方法名和参数个数/参数类型确定的,参数个数不同或类型不同的话是不同的方法。
3)函数类型是逆变的,但你的例子不是函数类型
hongjiang,你好,谢谢你的回答。
这里的Father和Son确实就是为了模拟一下里氏替换原则。是重载overload,而非重写override。
我的困惑是,里氏替换原则为什么要求子类重载父类的方法时,要求方法的参数要比父类的参数类型更宽。
难道比父类的参数类型窄了。就不能替换父类了么?子类继承自父类,肯定拥有了父类的方法。然后重载一个参数类型更窄的方法时,只是在父类的基础上多了一个属于子类自己的方法而已。这样的话,子类也是照样可以代替父类的,也没有违背里氏替换原则。
既然没有违背,为什么有子类重载父类的方法时,要求比父类方法参数更宽的类型这个限制呢?
求解释。
overload 是表示同名不同参的方法,跟里氏替代没有任何关系。里氏替代是子类(实现)可以替代父类(接口),行为的替代是通过override体现的。
不明白你描述的LSP具体是在讨论什么,感觉这里混淆的地方可能是在于形参类型(formal parameter types)和参数类型(type parameters)的区别,参见
引用地址没显示:http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.2
谢谢你的回答。
djjdj
王先生您好,我是猎头nick,不好意思打扰了。
华为正在招聘高端职位,您是他们寻找的候选人之一,请问方便联系吗?期待您的回复。我邮箱是nick.cai@dsi.com.cn。
请问《Functional Programming in Scala》中文版什么时候才可以买到呢?
谢谢老师!
内容翻译已经完成,现在在第二次矫正中。但后续流程我不知道要多久。
您好,本人在美国就读计算机类研究生,最近在上Scala有关的课程,从知乎上找到了您的博客,很多东西写的非常好,本人想做一些文章翻译然后用于与教授同学共享讨论,也可能会发在我自己的博客上,不知道您是否愿意授权于我去做这样的事情。
没有问题,如果发现错误或问题也欢迎指出。
hongjiang,您好:
看了《scala在挖财的实践》不由得要竖大拇指,后来想起来一个问题想请教下:akka这部分,当因为数据量越来越大,需要类似集群那样来扩展时,你们在akka这块具体怎么弄的呢?因为听你演讲说没有用akka的集群,所以对这个感到奇怪,特地请教!
希望能适当深入、具体点,谢谢!
你说的扩展性问题,并不一定要用集群来解决。因为akka的actor本身就支持remote actor,所以当把角色定义清楚,让这些actor之间远程通讯就可以了。集群相对复杂,它除了解决扩展性还解决高可用的问题,在不是非常必要的情况下可以不用引入集群。
谢谢hongjiang,最近在调研akka,想到了这个问题,打算实际验证下,有没有相关好资料推荐下,谢谢!
最好的是官方的文档,可以下载pdf打印成书,也可以搜一下akka相关的书籍,但书籍的版本未必跟得上,要注意。
hongjiang,您好:
官方remote的例子我搞清楚了,但是之后想起来实际的工程应用时,心里还是有疑问,特在此请教:
以金融行业计息的例子为例,有两个问题:
1、假如待处理的数据越来越多,一个机器上的actor实例怎么自动扩展来处理越来越多的数据呢?
2、在超出一台机器处理能力范围之外的数据,创建remote actor的时候,url中包含了远程机器的ip、端口号之类的信息,这样看来扩展时需要技术人员设计、开发等方式的介入,想请教在这样的情况下,有没有什么办法能够自动弹性支撑数据量的扩充呢?
谢谢!
不好意思,hongjiang:
还有个问题,很多数据要处理的情况下,为了保证不遗漏,是不是要在一个地方把数据分片后通知到各个负责处理数据的actor,或者由这些actor从一个地方集中获取每个actor处理的数据的范围?
有没有更好的办法?
谢谢!
谢谢hongjiang,
找到了一个官方的demo,打算好好分析下。回头可能会整理个分析文档。
您好,我们做培训的,想请您给我们客户做scala-spark方面的培训,您要是有兴趣可以联系我。
没有精力。
想看看pandora相关的设计思想或者代码,不知道哪里可以找到代码,非常感谢。
Pandora没有开源,你可以关注一下java9里的模块化。
文章写得很棒!怎么可以订阅呢?
https://hongjiang.info/feed/
为啥我点开之后直接是一个代码页呢..
不知道下一步怎么走
—
有点迷茫
—
你好。
博主已经很久没有更博了。。。
您好,宏江,我是scala爱好者,现居杭州,研究了众多函数式语言之后,觉得凭借scala的能力,将来有没有可能scala会逐渐替代java,成为企业级开发,大数据应用的主流?scala目前还没有在国内普及,阻力到底在哪里?您是scala的专家,想就这个问题和您深入探讨一下。
不会替代java,门槛较高,大部分开发者不需要这种复杂度。
宏江你好,
我是scala的初学者,有个问题想请教一下。scala不是有两种声明变量的方式,var和val,val实际上是声明一个不变的常量。但val好像对array里的元素不起作用,尽管用val声明一个数组,但数组内容一样是可变的:
//下面是例子:
scala> val arr = Array(“Hello”, “World!”)
arr: Array[String] = Array(Hello, World!)
scala> arr(0) = “Goodby”
scala> arr
res25: Array[String] = Array(Goodby, World!)
scala>
//
是不是val对集合不起作用?
谢谢
这个是基本概念.
不可变的是 arr引用指向的地址.
也就是不能再对arr赋值.
但由于arr指向的是Array, Array可能修改其元素的内容.
如果你用arr转向一个 immutable.Map, 那么你也是不能修改里面的内容的, 就跟你现在想的一样.
点赞:博主还在坚持更新
今天查问题[Scala] 才发现这个宝藏UP.
速速看了几篇, 每个都能解答我的一些困惑.
翻了几个交流信息, 原来是阿里的大佬. 现在好像在别的地方发展了. 祝福.
看了下近一两年, 更新频率好像低了很多. 哪里可以看到up最新的更新呢.
谢谢关注,这几年的人生境况有些多变,没有心思写;稳定下来会继续记录一些所见所闻以及感受。
搜索技术的时候发现了你,别来无恙。感谢曾经的帮助和指导。
好些年没消息,你还在北京吗?回去后有空可以聚聚。
Scala中国社区还活跃么?网上搜了下发现网址没法访问,或者有微信群么?