找回密码
 马上注册

QQ登录

只需一步,快速开始

查看: 16082|回复: 15

【原创】【iRobot的机器人编程笔记】(五)从Hello World开始学习Java的API(下)

[复制链接]
20 乐币 回复本帖可获得 5 乐币奖励! 每人限 1 次(中奖概率 50%)
发表于 2013-5-27 18:21:27 | 显示全部楼层 |阅读模式
本帖最后由 iRobot 于 2013-5-28 18:04 编辑


       新的一课开始了!照例先讲一堆废话。

       首先要说的是,我们网友群体的年龄层次跨度十分大,从小学五,六年级到孩子十来岁的都有。所以课堂内容的把握让我比较头疼。我想在未来2课依旧保持在这个深度层次,等讲完Eclipse之后,适当加深一下。有什么意见赶快提,过期不候。哈哈。

       其次我要说,同样是教学,中国人写的书或教程要更好。当然我不是指我的这个系列教程。中国人讲解知识,讲究的是深入浅出,循循善诱,让人尽可能的读懂。美国人通常一味的堆砌专业词汇,死板,生硬,处处只顾“彰显”自己多么的专业。所以大家到书店选教材的时候,应该尽可能支持中国人的著作。

       以上内容属个人观点。

       下面开始正式课程!

1.      对象,方法,属性。

       又回到这里了。上一课有一个概念,我没有讲清楚。因为比较绕口,所以放在这里专门讲一下。我在之前的讲述中,有时候用对象,方法,属性这3个词,有时候用类,方法,属性这3个词。那么这两组概念到底是不是一个东西?是。确切说,静态类是对象,非静态类实例化之后是对象。静态类中的方法都是静态方法,非静态类里也可以有静态方法。下面通过几个例子讲解一下静态类和非静态类。

  1. LCD.drawString(“Hello World”,0,0);
复制代码
       不错,这个例子早就讲过了,大家应该也会用了。我要讲的知识点就在这里。打开你的API文档,还是通过索引(Index)找到LCD的drawString方法。

32.png

       红色处,static void表明这是一个静态方法,所以你可以直接拿来用。实际上LCD是个静态类,其中的所有方法都是静态方法,这说明你可以直接通过类名.方法的方式来使用其中的所有内容,这就是静态类的特性。下面说一下非静态的。在你的API中搜索drawString。

33.png

       可以看到我标注的红线处有4个drawString方法。下面两个是LCD类中的,上面两个是Graphics类的。这说明“显示文字”至少有4种方法,而Graphics就是非静态的。跳转到Graphics中的drawString(String, int, int, int)方法看看。

34.png

       就方法本身而言,和LCD是完全一样的,一点差别都没有。但是注意红色标注处,没有static字样,说明这不是一个静态方法,不能直接拿来使用。使用前,应当先实例化一个对象:
  1. Graphics g =new Graphics();
  2. g.drawString(“Hello World”,0,0);
复制代码
       第一行的意义,就是将非静态类实例化,实例化之后,g就可以作为一个对象(同LCD一样)来使用了。这就是对象和类之间的那个“等号”,以后的内容中,为了严谨,均使用“对象”一词代替“类”。

2.      为什么要有静态和非静态之分

       学过C语言的同学都知道,我们没有必要把成百上千的.h文件全包括到自己的项目中。同样,我们的Java程序也没必要在启动时加载所有的类。最常用的,做成静态的,不常用的,需要的时候再通过实例化调用。但区别不仅仅在此,我举三个例子。
       例一:
  1. LCD.drawString(“123”,0,0);
  2. LCD.drawString(“456”,0,1);
复制代码
       在调用LCD中的drawString方法时,两个输出必然是先后进行的。但是看下面的代码:
  1. Graphics g1 =new Graphics();
  2. Graphics g2 =new Graphics();
  3. g1.drawString(“123”,0,0);
  4. g2.drawString(“456”,0,1);
复制代码
       这是两个对象,是同时进行输出的。非静态类我们可以实例化出多个对象,同时使用,或者完成一些相似而又不同的功能,比如我们可以:
  1. g1.setColor(Color.White);
  2. g2.setColor(Color.Black);
复制代码
       通过设置两个对象的文字颜色,g1专写白字,g2专写黑字

       例二:
  1.                 // 输入 1-A马达转动,2-B马达转动,3-C马达转动
  2.                 int input = 1;
  3.                
  4.                 if (input == 1) {
  5.                         Motor.A.rotate(720);
  6.                         Motor.A.stop();
  7.                         Motor.A.rotate(-720);
  8.                         Motor.A.stop();
  9.                         Motor.A.flt();
  10.                 } else if (input == 2) {
  11.                         Motor.B.rotate(720);
  12.                         Motor.B.stop();
  13.                         Motor.B.rotate(-720);
  14.                         Motor.B.stop();
  15.                         Motor.B.flt();
  16.                 } else if (input == 3) {
  17.                         Motor.C.rotate(720);
  18.                         Motor.C.stop();
  19.                         Motor.C.rotate(-720);
  20.                         Motor.C.stop();
  21.                         Motor.C.flt();
  22.                 }
复制代码
       我是希望根据用户选择,1,2,3,来将A,B,C马达正转2圈,再倒转2圈。通过查询得知Motor是一个静态类,其中的Motor.A是静态属性(属性又是另外一个类),使用Motor.A.rotate(720);是完全正确的静态类用法。但是下面3个if语句的内容何其相似啊,就是一遍遍的复制黏贴。如果我们用非静态类的用法来改动一下:
      
  1.        // 输入 1-A马达转动,2-B马达转动,3-C马达转动
  2.        NXTRegulatedMotor motorn = new NXTRegulatedMotor(null);
  3.        int input = 1;
  4.        switch (input) {
  5.        case 1:
  6.            motorn = Motor.A;
  7.            break;
  8.        case 2:
  9.            motorn = Motor.B;
  10.            break;
  11.        case 3:
  12.            motorn = Motor.C;
  13.            break;
  14.        }
  15.        motorn.rotate(720);
  16.        motorn.stop();
  17.        motorn.rotate(-720);
  18.        motorn.stop();
  19.        motorn.flt();
复制代码

       在实例化对象时,根据参数选择实例化成Motor.A或B,C,然后使用时仅需调用motorn对象的方法就可以了。大家在写代码时,有一个原则是尽可能避免重复。这是非静态的另外一个优点,根据需要实例化成特定的对象。当然两者的区别不仅限于此,两者也不是一成不变的,是可以互相转化的,不过这些超出了我的课程范围。

       例三:
  1. TouchSensor touch = new TouchSensor(SensorPort.S1);
复制代码
       一行代码就足够了。它的作用是调用触碰传感器。因为马达和ABC端口是一一对应的,所以Motor类可以做成静态类。但是触碰传感器可能插在S1,S2,S3,S4中的任意端口,因此不可能被设计成静态类。必须在调用时通过构造函数确定实例化为哪个端口上的对象。
3.      换一个角度看API

       现在大家至少知道了3个类的用法:LCD,GraphicsMotor。但是都是我带着大家“从下往上”看的。下面讲讲如何“从上往下”看。这次我们通过Index找到TouchSensor类。

35.png

       这里框1和LCD类是相似的。之前讲解时略过了,此时详解一下红色喷漆处。

       第一行:java.lang.Object说明TouchSensor 继承自java.lang.Object类。这是纯Java中的一个标准类(应该说是所以对象的基类),继承自这个类,才说明LeJOS是基于Java的一种开发语言。“血统纯正”。如果不继承自这个类,那我们也不能这么舒舒服服的使用Java的语法和编译器了。

       第二行:lejos.nxt.TouchSensor 说明我们的TouchSensor类在LeJOS语言中的从属关系。是隶属于lejos类下的nxt类下的TouchSensor类(实际上应该是lejos.nxt类,并且TouchSensor类本身可能还有子类)。明白这个从属关系很重要,方便我们自学。学校是不会开设LeJOS课程的,书店也没有LeJOS的书籍卖,所以很多事情要靠猜的。嘿嘿。

       打开API,点击Overview(在Index那行的第一个)。这正是提供给开发人员从上至下的阅读方式。找到lejos.nxt(有时候一个类结构会很长,很长,从哪里断开全靠缘分)。向下翻到Class Summary(类集合),可以找到我们上边用过的TouchSensor,触碰传感器。

36.png

       在TouchSensor上面的,是TemperatureSensor(温度传感器),下面的是UltrasonicSensor(雷达传感器)。还记得在第三课中,我误把加速度传感器当做雷达的那个例子吧?现在你应该可以看着UltrasonicSensor的类说明自己改正过来了。实际上,相似的类会放在同一个命名空间下,所以我们所有的传感器,都可以在lejos.nxt的Class Summary中找到。

       还是点击Overview,回到类列表。老规矩,我简单翻译几个,剩下的自己思考。

java.awt 绘图
java.awt.geom 绘图
java.lang 核心
java.lang.annotation 核心
java.net 网络
java.util 公共类(数据集合,时间函数等)
javax.bluetooth 蓝牙


       具体都包含哪些内容,可以点进去查看。

4.      Tree视图

       除了讲过的Index和Overview两种浏览方式,你还可以通过Tree浏览。顾名思义,所谓的Tree(树),就是将类的从属关系一层层展开来显示。类似书籍中的目录,大纲。

5.      NXT和PC是不同的API

       从一开始,我就说过,我们打开的是NXT Doc API。那么在开始菜单中,还有一个PC Doc API。两者有什么异同呢?差别肯定是有,一个适用于开发NXT上运行的程序,一个适用于开发PC上运行的程序。注意一定要对号入座,否则肯定会出错。关于PC Doc API我就不讲了,原则上和NXT文档是相同的。但是实际工作方式不同。我只举两个例子提示一下思路:

       区别一:
       NXT和PC中都有Button类,但是NXT的Button指的是NXT主机上的左右确认退出四个按钮,PC上指的是屏幕上绘制出的按钮,比如“登陆”“注册”“下一步”“确定”等等。

       区别二:
       NXT和PC中都可以用new Date().getDate()方法获取当前日期,但是PC中获取的是当前时间,NXT本身没有“钟表”的功能,所以它获取的时间永远是2000年1月1日,你开机5分钟,就会走到00:05分(通过晶振计算得出)。虽然不能当“钟表”用,但是可以用于计算时间差。

6.      后记

       1. API的内容就全部讲完了。这时建议大家再看看动力老男孩和Programus翻译的LeJOS文档,应该会读懂其中的内容了
       2. 再吐槽一次,虽然LeJOS提供了这么多种API的浏览方式,却缺少最最有用的“搜索”功能。
       3. 下一课通过一些小技巧简述一下流程语句和线程。

如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
发表于 2013-5-27 21:01:05 | 显示全部楼层
出来啦。先定后看,谢谢!
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2013-5-28 13:00:28 | 显示全部楼层

回帖奖励 +5 乐币

LeJOS 支持EV3不?
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2013-5-28 21:15:53 | 显示全部楼层

回帖奖励 +5 乐币

照例学习,谢谢了。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2013-6-2 09:09:18 | 显示全部楼层
“从小学五,六年级到孩子十来岁的都有”,这样的孩子都能看懂啊,真是佩服,看来不得不承认30多的人搞半天没明白确实是老了!!!
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2013-6-2 10:00:43 | 显示全部楼层
caihc 发表于 2013-6-2 09:09
“从小学五,六年级到孩子十来岁的都有”,这样的孩子都能看懂啊,真是佩服,看来不得不承认30多的人搞半天 ...

孩子的话,还是以启蒙和激励为主了。呵呵。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2013-6-3 15:33:22 | 显示全部楼层

应该是支持的。。。万变不离其宗嘛,再说“向下”兼容应该没问题
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2013-6-3 21:27:16 | 显示全部楼层

回帖奖励 +5 乐币

楼主你好,很感谢你的工作,我现在也在做lejos的开发,我想问一下lejos的pc开发文档在哪里呢?如何将一部分程序在pc上运行而不上传到brick上呢?我用的是eclipse的环境,最近比较急着解决这样的问题,如果楼主方便的话能否解答一下呢?万分感谢!
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2013-6-3 21:38:21 | 显示全部楼层
Frank_yang 发表于 2013-6-3 15:33
应该是支持的。。。万变不离其宗嘛,再说“向下”兼容应该没问题

我同意。 首先技术上来讲,应该不算太难。其次如果Ev3不支持,那么以后4,5,6就更不会支持了,等于放弃了这块市场了,之前的开拓不是打了水漂。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2013-6-3 21:48:19 | 显示全部楼层
blabla 发表于 2013-6-3 21:27
楼主你好,很感谢你的工作,我现在也在做lejos的开发,我想问一下lejos的pc开发文档在哪里呢?如何将一部分 ...

你既然已经用Eclipse来开发了,那我就默认为你具备相当的开发能力了。

如果你说的开发文档指的是API的话,就位于开始,所有程序,LeJOS NXJ之下。除此之外没有专门的PC开发文档。你也可以看一下LeJOS 的帮助文档,里面也提到了PC的部分内容。  至于如何让“一部分程序运行在PC上”,这个按照我目前掌握的知识来看,两者应该是“几乎无关”的两个东西。分别写好之后通过NXTConnector 或类似UDP的方式交换数据。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2013-6-4 17:16:02 | 显示全部楼层
iRobot 发表于 2013-6-3 21:48
你既然已经用Eclipse来开发了,那我就默认为你具备相当的开发能力了。

如果你说的开发文档指的 ...

嗯,谢谢楼主的耐心,我现在正在做这方面的东西,不知道我们是不是可以交换一下联系方式,我刚开始做,还有很多东西不大明白的,可能还有很多问题想要请楼主赐教呢。。。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2013-6-12 23:05:10 | 显示全部楼层
楼主的教程很详细,有用!
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2013-6-13 10:44:42 | 显示全部楼层

回帖奖励 +5 乐币

收藏了。楼主辛苦
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2013-6-17 21:44:40 | 显示全部楼层

回帖奖励 +5 乐币

继续学习。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2014-2-18 17:57:11 | 显示全部楼层
静态类是对象,非静态类实例化之后是对象。静态类中的方法都是静态方法,非静态类里也可以有静态方法
这句话不准确。
应该是每个类都是Class这个类的一个对象,而实例化后的对象是相对应的类的一个对象。类的静态方法是属于整个类的,可以在类加载后,创建实例之前被使用。非静态方法是属于某个特定实例对象的,所以必须先实例化一个对象出来才能用。
如果不是内嵌类,类是不分静态不静态的。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|中文乐高 ( 桂ICP备13001575号-7 )

GMT+8, 2024-3-29 05:08 , Processed in 0.517091 second(s), 27 queries .

Powered by Discuz! X3.5

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表