原标题:简单的this,麻烦的this

猿 份

周末的Hello World咖啡馆总是热闹非凡。

Java , Python, Ruby, Java围坐在一起,一边喝咖啡,一边海阔天空。

C老头儿则待在一旁,冷眼旁观。

聊着聊着,这话题不知怎么着转移到了“this”上来了。

Java 说: “唉!你们不知道吧,对于一个初学Java的人来说,this 是非常难于理解的。”

Python说:“this 在你那里已经够简单了啊。还难于理解?”

“我们都是支持面向对象编程的,在我这里,this 可以用到实例方法或者构造器中,表示对当前对象实例的引用。”

publicclassPoint{

privatedoublex = 0.0;

privatedoubley = 0.0;

publicPoint(intx, inty){

this.x = x;

this.y = y;

}

publicdoubledistanceTo(Point that){

doubledx = this.x - that.x;

doubledy = this.y - that.y;

returnMath. sqrt(dx*dx + dy*dy);

}

}

“这不很容易理解吗? ” Ruby 问道。

“对于第一次接触面向对象编程的人来说,他分不清这个当前对象this到底是哪个对象。” Java说,“我必须得再写一段代码给他掰扯一下。”

Point p1 = newPoint( 1, 1);

Point p2 = newPoint( 2, 2);

//this指向的是p1

p1.distanceTo(p2);

//this指向的是p2

p2.distanceTo(p1);

“对啊,this必须得有个上下文才能准确理解。” Python说,“还有,你那个this吧,是个隐式的,像我是显式的:”

classPoint:

def __init__( this, x, y):

this.x = x

this.y = y

def distanceTo( this,point):

dx = this.x - point.x

dy = this.y - point.y

returnmath.sqrt(dx** 2+dy** 2)

Java 说:“你不是一直用self吗,怎么现在是this?”

Python笑道:“我这不是为了和你Java老弟保持一致嘛,反正只是个变量名,你想用this就用this,想用that就用that,只不过我们习惯于用self 。”

Ruby说: “Python兄,你把this放到方法中作为一个参数,实在是太丑陋了,一点美感都没有。”

“那是我们的哲学,我们信奉 Explicit is better than implicit。”

“可是在调用的时候,怎么不把一个对象传给那个方法?你的self去哪里了?”

p1 = Point(1,1)

p2 = Point(2,2)

p1.distanceTo(p2)

p2.distanceTo(p1)

“你怎么不写成: distanceTo(p1,p2) ?”

“那不行,” Python说,“如果那样的话我们就不是面向对象了,而面向过程了。”

“哼哼,” C老头儿在一旁冷笑一声,“说来说去,还不是披了一层面向对象的外衣,内部实现依然是面向过程的?!”

“此话怎讲?” Java一直以正统的面向对象自居,不像Python, Ruby ,Java即使是想输出一个Hello World也得定义一个类不可。

“就说你吧,Java小子,你的Java 源文件被编译以后变成了.class文件, 这个class文件被装载到了Java虚拟机的一个区域,这个区域叫什么?” C 老头儿出手不凡。

“当然是Method Area, 方法区了,这我会不知道?!”

“对啊,它为什么叫方法区? 为什么不叫Class Area, 类区?” C 老头儿真是别出心裁。

“这…… ” Java 语噻了,他从来就没有想过这个问题。

“你的方法区是被各个线程所共享的,存储虚拟机加载类的信息,常量池,其中最主要的就是类中定义的方法相关的代码。 而你创建的对象呢,却是放在‘堆中’,虚拟机在执行的时候,要从方法区找到‘方法’,这些方法的字节码在运行的过程中,会操作位于堆中的对象。 ”

“所以你看,你的数据和方法是分离的,一个地方是方法(所以叫方法区),一个地方是数据,和我们C写出的程序是一样的,都是面向过程的!” C老头儿经过一系列证明后做了最终陈述。

Python也沉默了,他知道,自己在运行时也和这种方式差不多。

过了一会儿,Java 醒悟了过来:“不对,老头儿你这是混淆概念,我们是站在程序员的角度在谈论语言是不是面向对象的,而你则把我们拉到了实现层面,这是不对的。”

Python也附和道:“对对,我们是面向对象的语言,抽象程度比你的面向过程要高!”

“抽象? 哼哼,” C 老头儿又冷笑一声,“Linus 用C 写了Linux,用C 写了Git, 你觉得他没有做抽象? 笑话! 依我看来,抽象就是要在变化的东西中找到不变的东西,和具体的编程语言关系不大啊。” C老头说了一句至理名言。

Java 悄悄对Python说: “老头儿主要做操作系统内核,操作系统中的那些虚拟内存,进程,线程,文件系统概念都很清晰, 并且很稳定,估计他没有接触到应用层变态的,不讲道理的业务逻辑。 ”

C 老头儿说:“别以为你们面向对象有多么了不起,我告诉你,有很多程序员,用着面向对象的语言,写着面向过程的程序!关键是人!”

Ruby 说:“两位兄台,算了,不和老头儿争论了,来看看我的this吧, 奥不, 是self, 我这里必须用self。 我的self 和你们的都不一样,在不同的位置表示不同的含义。比如说:”

classPoint

# 此处的Self 就是Point这个类

puts "Self is :#{self}"

# 定义一个Class级别(静态)的方法,self还是Point这个类

defself.name

puts "Self inside class method is: #{self}"

end

# 定义一个实例方法, 此处的self 就是对象实例了

defname

puts "Self inside instance method is: #{self}"

end

end

Java 说:“你这搞得太麻烦了,定义一个静态方法,用static 不就结了?”

半天都没有说话的Java突然说道:“这也叫麻烦,来看看我是怎么处理this的!”

functionadd(y){

returnthis.x + y

}

熟悉面向对象的Java, Python看到这么古怪的代码,大为吃惊, 这是什么鬼? add函数中的这个this 到底指向谁?

Java说:“不要大惊小怪! 我的this和你们的this ,self都不一样,它是动态的,在定义时确定不了到底指向谁,只有等到函数调用的时候才能确定,this 指向的是最终调用它的那个对象,比如:”

functionadd(y){

//此时的this 指向的是全局的对象,在浏览器运行就是window

returnthis.x + y

}

x = 10

console.log(add( 20))

在这里调用add函数的是全局上下文, 所以this指向的是全局对象,输出的值是30 。

Java说:“我还可以给add函数传递一个对象当作this。”

functionadd(y){

//此时的this 指向的是对象obj,this.x 是20 ,不是10

returnthis.x + y

}

x = 10

varobj = { x: 20};

//传递一个对象给add函数

add.call(obj, 20) // 40

大家更加吃惊了。

Java又展示了一个例子:

varobj = {

x: 100,

print: function(){

console.log( this.x);

}

}

obj.print() //100

Python说: “这个很容易理解,这个this应该是指向obj这个对象实例, 所以print函数输出的x是100,对吧。”

“对的,再来看一个:”

varobj = {

x: 100,

y:{

x: 200,

print: function(){

console.log( this.x);

}

}

}

obj.y.print() //200

Java 说道:“按照你的规则,这个this 指向的应该是最终调用它的对象,那就是y , 在y中,x是200,所以应该输出200 !”

Java说:“如果我把对象y中的x:200 给去掉,输出是什么? ”

“难道是100 ? 不, 它不会向上一级去找,只会在y中寻找x 的值,如果没有,就是undefined, 唉!你这this规则实在是太麻烦。”

Java笑了笑:“再来看个更古怪的例子:”

varobj = {

x: 100,

y:{

x: 200,

print: function(){

console.log( this.x);

}

}

}

varpoint ={ x: 15, y: 15, f: obj.y.print}

point.f() //输出什么?

varx = 10

g = obj.y.print

g() //输出什么?

Python说:“这不还是一样嘛, 都应该输出200。”

Java说: “不,point.f() 应该输出15, 注意此时f 是对象point的一个函数,最终调用f 的是point对象,此时x = 15 了! ”

Java接口说:“我明白了,调用函数g()的是全局对象,x = 10 ,所以应该输出10 。”

Python说:“你小子号称前端之王,就这么用this来折磨程序员?”

Java笑道:“其实吧,普通程序员直接操作this的机会也不太多,都被框架、类库封装好了!”

这时候就听到C老头儿在那里摇头晃脑: “简单就是美,简单就是美啊。你们这帮小子,把世界搞得这么复杂,让程序员们学习这么多不必要的复杂性,真是浪费生命啊。”

“浪费生命? 没有我们这些语言,怎么可能创建出这么多Web应用程序出来? 你行吗?”

“我是不行,我只知道你Java 虚拟机是用我C语言写的, 你Python解释器,Ruby解释器也是C语言写的, 就连JS的V8引擎也是用我的兄弟C++语言写的。”

C 老头儿把手中的咖啡往桌子上狠狠一摔,转身就离开了咖啡馆。

— T H E E N D —

转载不用于任何商业用途,如侵权请联系我们马上处理返回搜狐,查看更多

责任编辑:

return this java_简单的this,麻烦的this相关推荐

  1. 好看的登陆界面java_简单又美观的登录界面

    蓝桥杯昨天结束了,小编发挥的很不好,不开心~ 所以,今天就不讲算法,讲一下看的见的jsp登录界面吧. 李春波 - 岁月(管弦乐版) 04:13来自浪潮之巅的小萝卜头 登录界面效果图: 是不是简洁又美观 ...

  2. 二进制反码求和java_简单又复杂的“整数类型”

    前言 因为一道题目让我不断地深追下去,挖出了我多年的噩梦--数据类型的范围与长度.每次都想得头痛,因为平台不同.编译器不同.编程语言不同等等因素,又没去做实验,网上那么多说法该相信谁都不知道--那不如 ...

  3. 文本文件 java_简单的用java实现读/写文本文件的示例

    简单的用java实现读/写文本文件的示例 更新时间:2008年07月26日 13:09:26   作者: 同时也展示了如果从输入流中读出来内容写入输出流中(仅限文本流) 三个例子可以独立存在,所以根据 ...

  4. return true Java_[Java教程]js中return,return true,return false的用法及区别

    [Java教程]js中return,return true,return false的用法及区别 0 2015-11-16 23:00:03 1.语法及返回方式 ①返回控制与函数结果 语法为:retu ...

  5. gradle插件 java_简单的Gradle Java插件自定义

    gradle插件 java 正如我在" 用Gradle构建Java的初步了解"一文中所展示的那样,当Gradle使用Java插件并将文件和目录放置在该插件期望的位置时, Gradl ...

  6. 线程池简单实现java_简单实现java线程池

    package com.ty.thread; importjava.util.HashSet;importjava.util.Set;importjava.util.concurrent.Blocki ...

  7. python c java_简单明了看懂JAVA,Python和C+的优劣势

    Java由于其优越的跨平台可移植性,在Web开发中是主流语言.在加上手机Android系统的发展,使得java开发人员的需求量很大.同时,Java现在也用来开发手游.Java 的语法相对规范. Pyt ...

  8. 框架层 java_简单就是美!浅谈java各层框架。

    很久没有来过Jdon了,感觉陌生了许多,也许有人看了我的标题以为我是一个ROR的鼓吹手,其实,刚好相反,基于现在开发的现状,我觉得JAVA阵营有必要站稳阵脚,分析清楚技术的走向,毕竟都涉及到我们的饭碗 ...

  9. kafka zookeeper java_简单搭建kafka + zookeeper,附简单Java生产和消费客户端

    首先说明一下这是一篇入门实战操作文章,本人亦是刚刚开始接触kafka,看了网上很多很多的文章,觉得自己也应当在搭建平台的过程中留下一些痕迹,总结一下遇到的问题和解决方法. 这篇文章主要是讲从零开始把服 ...

最新文章

  1. java基础学习(1)-jre与jdk
  2. 机器学习算法总结--提升方法
  3. zookeeper分布式锁原理及实现
  4. 适合初学者的安卓开源项目_开源初学者的6个起点
  5. java extjs combobox_extjs的combobox的用法
  6. iOS开发拓展篇—CoreLocation地理编码
  7. OSError: [WinError 126] 找不到指定的模块。【专治疑难杂症】
  8. 如果有一天不做程序员了,还能入什么行业?
  9. 《21天学通C语言(第6版•修订版)》一1.7 问与答
  10. SpringMVC中get请求中文乱码问题
  11. 用python做乘法口诀表_如何用python编写乘法口诀表
  12. 使用华为短信包,发送短信Result=61问题解决
  13. 使用百度人工智能识别表格
  14. python格式化千分位数字
  15. 360html收藏夹,360浏览器的收藏夹如何保存?360浏览器收藏夹备份方法
  16. 关于技术博客--找工作--这些年--陆续的
  17. 五彩斑斓的黑,找到了
  18. P1000 超级玛丽游戏题解
  19. 百度云非 VIP如何作弊加速?
  20. 2019计算机专业保研经历(清华、南大、上交)

热门文章

  1. android电子书小程序,小程序安卓手机无法打开pdf(解决)
  2. java学习+JDK下载安装环境配置+IDEA安装下载简单使用
  3. 带你玩转有向图------有向图(详解)
  4. 独立经济体——投机者的游戏
  5. Java技能:Java数据库概念模型设计
  6. Richard Feynman, 挑战者号, 软件工程
  7. 2016年主机游戏大作全方位预测
  8. Cognos 11.0快速开发指南 Ⅰ
  9. 【pytorch】ECA-NET注意力机制应用于ResNet的代码实现
  10. mysql的mgr是什么意思_MySQL之MGR简介