火山软件开发平台入门

 

一、面向对象的程序设计方法

面向对象的程序设计方法是目前最先进的程序设计理念,也是被目前绝大多数程序设计语言都使用的一种程序设计方法,它可以最大限度地提高程序代码的可复用性和可维护性,如果您想学习程序设计,那么这种设计方法是必须需要掌握的。

为了降低用户的学习门槛,火山对这套理念进行了最大限度的精简,一些晦涩难懂的和一些不大常用/实用的内容均被剔除出去,只保留了其精华和必须需要掌握的部分,因此学习起来并不难。

让我们根据一个实际生活中的例子来具体说明:

● 假设有一家工厂,所生成的产品是电水壶,这种电水壶有这些主要特点:

1、由壶体和壶盖组成;

2、颜色是银白色的;

3、有一个开关可以控制启动烧水;

4、水烧开后会发出鸣叫声音报警。

按照面向对象的设计方法,我们把这个电水壶称为这个工厂的一""产品,简称为“电水壶类”,它具有同样的4个特点:

1、有两个成员变量:壶体和壶盖;

2、有一个成员属性:颜色,它的值等于银白色;

3、有一个成员方法:烧水(即按下开关就开始烧水);

4、有一个成员事件:水已经烧开警报

变量用来存储类中的数据,属性用来表达或修改类的特征,方法用作执行类的功能,事件用来对外发送通知,就是记录有一系列变量属性方法事件成员的集合,所有具有这些特征成员的具体产品就叫做这个类的对象,这就是面向对象的程序设计理念来由

用前面的例子来讲,“电水壶类”就是电水壶的产品设计规范,而具体的单个电水壶产品就是“电水壶类”的对象(有时也叫对象实例)。

这就是类的封装

 

假设有一天,工厂想生产一种具有自动保温功能的电水壶,有两种方案:一是完全重新设计一个新的电水壶,二是在现有电水壶的基础上增加一个保温开关。很显然,第二种方式更经济实惠,工厂把这种新的电水壶称为保温电水壶,它增加了一个特点:

1、增加了一个开关: 保温,按下开关后可以对已经烧开的水进行自动保温。

按照前面的设计方法,由于新电水壶增加了一个成员,所以我们不能把它归纳到已有的“电水壶类”里面,但是我们可以建立一个新的类:“保温电水壶类”,它在“电水壶类”的基础上同样增加了一个新成员:

1、成员方法:保温(即按下开关就开始保温)

由于它基于“电水壶类”设计而来,因此我们把“电水壶类”称为“保温电水壶类”的基础类,把“保温电水壶类”称为“电水壶类”的继承类,它们之间是继承被继承的关系,继承类自动具有基础类的所有特征成员。

由于继承类包括了基础类的所有成员,因此继承类也可以认为是基础类的一种。这个也很容易理解:我们可以把“保温电水壶”称为“电水壶”,但是不能把“电水壶”称为“保温电水壶”。假设客户要买1000个“电水壶”,现有产品数量不够时我们可以用“保温电水壶”来充数,但是客户要买1000个“保温电水壶”就绝对不能用“电水壶”来充数,是不是这个道理?

从程序设计的角度来讲,就是我可以把一个数据类型为“保温电水壶类”的对象赋值到一个数据类型为“电水壶”的变量,但是不允许把一个数据类型为“电水壶”的对象赋值到一个数据类型为“保温电水壶类”的变量。

需要注意的是:如果把一个数据类型为“保温电水壶类”的对象赋值到一个数据类型为“电水壶”的变量,那么这个变量里面实际存储的还是一个“保温电水壶类”对象,并不会因为变量的数据类型为“电水壶”存储进去的对象的数据类型就也为“电水壶”了。这个也很好理解:工厂用“保温电水壶”充作“电水壶”交付给了客户,不会因为这个充数行为就导致“保温电水壶”产品变成“电水壶”产品了。

这就是类的继承

 

让我们继续假设,假设有一天工厂发现电茶壶的销路要比电水壶好,同样有两种方案:一是完全重新设计一个新的电茶壶,二是修改现有电水壶的烧水功能,将其改为烧茶。同样很显然,第二种方式更经济实惠。那么这种电茶壶的特点为:

1、修改了电水壶的烧水功能,使其改去烧茶。

同样,我们需要定义一个名为“电茶壶类”的类,然后定义一个同样名为“烧水”的方法,该方法覆盖了“电水壶类”中的原有名为“烧水”的方法,然后将“电水壶类”中的“烧水”方法标记为虚拟方法(虚拟方法仅是一个标记,用作标记“烧水”方法可以被继承类覆盖),这样以后调用“电茶壶类”类的“烧水”方法时,就会改去烧茶,而不会去烧水。

需要注意的是:如果把一个数据类型为“电茶壶类”的对象赋值到一个数据类型为“电水壶”的变量,据前所述,这个变量里面实际存放的还是一个“电茶壶类”的对象,因此如果调用该变量的“烧水”方法,实际上调用的还是“电茶壶类”的烧茶功能。

这就是类的多态

 

● 以上就是火山中所使用的面向对象程序设计的全部内容了,最后一点其实与面向对象设计无关:

假设甲公司和乙公司都生产电水壶,商店如果同时进货了这两种电水壶,就必须在电水壶上分别贴上标签:“甲公司的电水壶”、“乙公司的电水壶”,以免引起混淆。

在程序设计里面,就对应为“甲公司.电水壶类”、“乙公司.电水壶类”,前面的“甲公司”和“乙公司”分别定义了一个命名空间,也叫做“”。包用作避免名称混淆,在同一个名称的包内,不允许存在相同名称的类,在不同名称的包内,可以存在相同名称的类。

所有在包中定义的类,其名称前被自动加上包名,“包名.类名”称为类的绝对名称。如果该类的名称在程序的所有包中均唯一或者在该类所处包内部引用此类,可以省略掉其包名来引用此类。

譬如,假设程序中不存在“乙公司.电水壶类”或者在“甲公司”包自身的代码内部,就可以直接使用“电水壶类”来引用“甲公司.电水壶类”。

注意:包名中间也可以包括句点,譬如“湖北.武汉.甲公司”或“湖南.长沙.乙公司”,这样的命名空间更明确清晰一些,也更具有唯一性。

 

● 我们用火山程序将前述的示例类定义出来:

具体例程请参见火山软件开发平台入门例程中的“火山面向对象设计”项目

 

二、面向对象的程序设计在火山中的应用方法:

定义包

每新建一个火山程序,都会在首部固定有一个不可被删除的包定义成员:

在“包名”列中直接填入你所自己的包名即可。名称可以随意填写,可以与其它火山程序所使用的包名一致,此时说明这些火山程序均位于同一个包中,也就是说,这些相同包名的火山程序中定义的类均具有相同的包名前缀。

包名中间可以包括句点,通常使用的名称格式为以组织或事物的从大到小排列,譬如:“湖北.武汉.递归公司”、“递归公司.软件开发部”、“火山系统.安卓平台.测试程序”等等,这些都可以,自己维护这些代码时觉得清晰易懂就行了。

如果不需要使用当前火山程序又不想把它从工程中删除,可以在名称前面加上“//”文本(“//”为火山系统的注释引导文本)将其在编译时屏蔽掉:

在程序中的所有各类成员定义表格中均可进行类似处理,只要在名称前加上“//”文本,那么该定义实体及其中的所有内容在编译时就会被全部屏蔽掉。

在“属性名”和“属性值”列中,可以填入对应当前所定义成员的系统属性(以‘@’字符开头,除非特意指出,一般用户无需了解)或者用户属性(仅针对数据类型为成员变量/局部变量有效,由该类的可写成员属性提供,见后)。

 

定义类

在编辑器中点击鼠标右键,选择“插入->插入新类”即可在当前程序所处包中插入一个新的类:

同样,在“类名”列中填入你所期望的名字就行了,与包名不同的是:

1、同一个包中不允许出现相同的类名;

2、类名中不允许使用句点。实际上包名是唯一允许中间使用句点的名称。

如果你的类使用了基础类,同样在“基础类”列中填入该类的名称即可:

此时,当前类将自动继承所有来自所指定基础类的内容,如果该基础类还有基础类,将一并继承过来。

类定义中还有一个“公开”列,用作定义类对外提供的访问权限。它是一个勾选列,被勾选表示为真,未被勾选表示为假。下同。

如果你勾选了“公开”,那么这个类在你的程序的任意地方都可以被使用,如果你没有勾选,那么这个类只能在它所处包的内部程序中被使用。

譬如,如果保持前面的“保温电水壶类”的公开列被勾选,那么下面的代码就可以正常使用:

如果你将“保温电水壶类”的公开列取消勾选,那么由于“测试类”所处的包“火山.测试”与“保温电水壶类”所处的包“湖北.武汉.甲公司”不一致,箭头所指向的代码就会编译失败。

当然,如果“测试类”也位于“湖北.武汉.甲公司”包里面,则还是可以访问的。

在程序中的使用方法和基本数据类型譬如“整数”、“文本型”是一样的,任何可以使用基本数据类型的位置都可以使用

两者之间唯一的不同在于:有子成员,而基本数据类型没有子成员。

譬如上图中的代码定义了一个“保温电水壶类”的“我的电水壶”对象实例,那么我们就可以使用“我的电水壶.壶盖”访问它的“壶盖”成员变量,使用“我的电水壶.烧水()”调用它的“烧水”方法。

在类的对象实例名称和欲访问的子成员名称之间使用句点分隔即可,前面指定具体访问哪一个对象实例(也就是说,假设有很多个电水壶,我要去使用哪一个),后面指定访问这个对象实例的具体哪个子成员。

 

定义类成员变量

成员变量用作类存储其数据时使用。

在类中点击鼠标右键,选择“插入->插入新成员/局部变量”即可在当前类中插入一个新的成员变量:

在“成员变量名”列中填入该成员变量的名称,要求在其所处类及其所处类的所有基础类中均唯一。

在“类型”列中填入该成员变量的数据类型,可以是基本数据类型譬如“整数”、“文本型”等,也可以是

公开”列用作定义类成员变量对外提供的访问权限:如果“公开”设置为真,表明该成员变量在所有程序位置都可以被访问,如果为假,表明该成员变量只能在其所处类或者其所处类的继承类中被访问。

譬如:前面“电水壶类”中的“壶盖”和“壶体”成员变量:

由于其“公开”未被设置,因此其只能在“电水壶类”及其继承类“保温电水壶类”中被访问,在程序中的其它位置均无法访问则两个成员变量。

其它类别的类成员(譬如方法、属性、事件)的“公开”列均是本作用,下面就不再累述。

成员变量的“静态”列如果被勾选,表明该变量为静态成员变量。静态成员变量有以下特点:

1、静态成员变量并未存放在类的对象实例中,而只存放在类本身中,所以无论定义多少类对象实例,静态成员变量都只存在一份;

2、由于静态成员变量存放在类本身中,所以在其所处类/继承类外部需要以“所处类名.静态成员变量名”的方式访问。

如上图,在“测试类1”中定义了一个名为“静态成员变量1”的成员变量,在测试类2中红色箭头所指向的代码是正确的访问方式,黄色箭头所指向的代码虽然也能被编译器所接受,但是由于不是推荐的访问方式会提示警告。

无论在“测试方法”方法中定义了几个“测试类1”的对象实例(“对象1”、“对象2”),“测试类1”的“静态成员变量1”始终只存在一份,因此红色和黄色箭头指向的代码所访问的“静态成员变量1”都是同一个。

成员变量的“参考”列如果被勾选,表明该变量为参考变量。参考变量有以下特点:

1、参考变量本身并不会定义对象实例,而是用作保存指向其它对象实例的“参考”,访问这个变量等于访问这个变量所参考到的另一个对象实例;

2、由于其本身并未定义对象实例,因此参考变量在使用前必须首先赋值(即赋予其所参考到的对象实例)。

想一想我们常用的耳机的插头,它就是“参考变量”的一个例子:当它连接电脑时,我们可以听到电脑播放的声音,当它连接手机时,我们可以听到手机播放的声音,这个“连接”动作就代表了对插头这个“参考变量”进行赋值( 指定其参考到电脑或手机)。当它未连接任何设备时(即未参考到任何对象实例时),当然什么声音都听不到。

请查看如下代码(通过局部变量演示,两者“参考”属性的作用是一样的):

首部定义了“电水壶对象1”和“电水壶对象2”两个“电水壶类”的对象实例,然后定义了一个名为“电水壶参考对象”的“电水壶类”参考变量。

两者的区别在于:前者创建了真实存在的对象实例,而后者仅仅用作存放一个参考。

由于“电水壶对象1”和“电水壶对象2”存在对象实例,因此后面调用其“烧水”方法不会有问题,而紧跟其后的“电水壶参考对象.烧水()”(红箭头指向)调用就会被编译器报错,因为其尚未设置所欲参考到的对象实例。

在后面通过将“电水壶对象1”赋值过去,从而将“电水壶参考对象”参考到了“电水壶对象1”,因此再调用“电水壶参考对象.烧水()”(青箭头指向)就不会出错了,其等效于调用了“电水壶对象1.烧水()”。

初始值列仅用作给基本数据类型的变量赋予初始值,譬如:

具体可用的基本数据类型及初始值格式见后面的语法讲解部分.

 

定义类成员常量

成员常量用作类存储其恒定不变的数据时使用。

不可被修改的变量”被称为“常量”,其也是成员变量的一种,因此在前面就没有单独阐述。

在类中点击鼠标右键,选择“插入->插入新常量”即可在当前类中插入一个新的成员常量:

常量与变量有以下不同之处:

1、常量只能在定义时被赋予初始值,不能在程序中被修改;

2、常量的数据类型只能为基本数据类型(注:还可以为常量类,但普通用户不需了解);

3、常量“静态”属性固定为真,即:常量并未存放在类的对象实例中,而只存放在类本身中,所以无论定义多少类对象实例,常量都只存在一份;

4、由于常量的数据类型只能为基本数据类型,所以“参考”属性对于常量来说没有意义。

常量的访问方式与静态成员变量的访问方式一样,在其所处类/继承类外部需要以“所处类名.常量名”的方式访问。

常量一般用作定义一些不会在程序中被修改的恒定值,譬如圆周率的PI。这样既能避免多次输入出错,还能提供程序的运行效率(便于优化)。

下图是在火山基本库的“数学运算类”中定义的2个数学常量,在需要使用这些值的地方可以使用常量来代替(如“数学运算类.E”、“数学运算类.PI”),避免输入错误:

 

定义类成员方法

成员方法用作类对外提供其所支持的功能时使用。

在类中点击鼠标右键,选择“插入->插入新方法”即可在当前类中插入一个新的成员方法:

在“方法名”列中填入该方法的名称,要求在其所处类及其所处类的所有基础类中均唯一。

方法的“类别”列可以选择“通常/属性读/属性写/定义事件/接收事件”5类,本处只讨论“通常”类别,其余4种在后面讨论属性事件成员时再阐述。

静态”列为真的方法与静态成员变量基本类似,在其所处类/继承类外部需要以“所处类名.方法名”的方式访问。两者之间不同的是:在静态方法内部,只能访问其所处类或者其所处类的基础类中的成员常量或者静态成员变量。譬如:

其中定义了一个名为“测试方法”的静态方法,其中第一行代码同时访问了类中的“静态变量1”和“常量1”,这是被允许的,然后后面的一行代码访问了非静态变量“变量1”(红色箭头指向处),这是不被允许的,编译器将报错。

返回值类型”列指定了方法返回值的数据类型。如果指定了非空数据类型,则方法中就必须调用“返回”关键字语句来返回对应数据类型的数据。

可以为方法定义一个参数表,用作指定调用此方法时所需要提供的参数:

需要注意的是:

1、数据类型为的参数始终以参考方式传递对象。譬如前面的“参数1如果在外部调用“测试方法 (电水壶对象1, 123)”,那么“参数1”将是指向“电水壶对象1”的参考,操作“参数1”等效于操作“电水壶对象1”

2、调用方法时,必须加上用小括号括住的参数表,即使该方法的参数表为空,也必须加上用小括号括住的空参数表。如,假设前面的“测试方法”没有定义任何参数,调用它时也必须使用“测试方法()”。

 

定义类成员属性

成员属性用作表达或修改类的特征时使用。

成员属性根据其可访问方式分为3类:“可读成员属性”、“可写成员属性”、“可读写成员属性”。

 

1、定义“可读成员属性”:

可读成员属性”用作支持对属性值的读取。

插入一个方法,将其“类别”列设置为“属性读”,然后保证其满足以下格式要求:

1、访问权限必须为“公开”;

2、不能为静态方法(实际上静态方法也可以用作定义属性,不过这个不需要普通用户掌握,有兴趣可以去查看语法手册);

3、没有参数;

4、必须定义有一个返回值,该返回值的数据类型即为该属性的数据类型

譬如以下代码在“测试类”中定义了一个数据类型为“整数”的可读属性“我的属性”:

注意:虽然“我的属性”是以成员方法的形式定义的,但是在程序中访问时不能以方法的访问方式“对象.我的属性()”来访问,而应该以访问“成员变量”的方式来访问,即:“对象.属性名”。

如,访问上面可读属性的语句为:

其中黄色箭头指向处定义了“测试类”的一个对象实例,红色箭头处读取了其“我的属性”的属性值并将其赋值到“整数变量1”。

实际上,读取“测试类对象.我的属性”时,等效于调用了“我的属性”属性读取方法。

 

2、定义“可写成员属性”:

顾名思义,“可写成员属性”就是用作支持对属性值的写入。它的定义方式与定义“可读成员属性”类似,只是所定义方法的格式要求不同。

插入一个方法,将其“类别”列设置为“属性写”,然后保证其满足以下格式要求:

1、访问权限必须为“公开”;

2、不能为静态方法;

3、只有一个参数,该参数的数据类型即为该可写属性的数据类型

4、没有返回值。

譬如以下代码在“测试类”中定义了一个数据类型为“整数”的可写属性“我的属性”:

同样,虽然此处“我的属性”是以成员方法的形式定义的,但是在程序中访问时不能以方法的访问方式“对象.我的属性(欲写入的属性值)”来访问,而应该以访问“成员变量”的方式来访问,即:“对象.属性名”。

如,访问上面可写属性的语句为:

其中黄色箭头指向处定义了“测试类”的一个对象实例,红色箭头处将其“我的属性”的属性值赋值为123。

实际上,写入“测试类对象.我的属性”时,等效于调用了“我的属性”属性写入方法。

可写成员属性”还有另外一种访问方式,就是直接在对象的属性表中设置,如:

等效于前面通过语句“测试类对象.我的属性 = 123”对该属性的写入。

操作小提示:要想知道当前对象有哪些“可写属性”,在“属性名”列上按下空格即可:

 

3、定义“可读写成员属性”:

很容易理解,“可读写成员属性”就是既可以被读取又可以被写入的属性,定义它的方式也很简单,就是同时定义名称相同的属性读属性写方法,如:

其中黄色箭头指向定义了“我的属性”的属性读方法,红色箭头指向定义了“我的属性”的属性写方法。

前面已经讲过,“可读属性”用作支持对类属性的读取操作,“可写属性”用作支持对类属性的写入操作,编译器会根据当前操作是读取还是写入自动调用对应的属性读/写方法。当以以下方式对“我的属性”进行访问时:

黄色箭头指向处将调用“我的属性”的属性读方法,而红色箭头指向处将调用“我的属性”的属性写方法。

定义“可读写成员属性”时需要注意的是:

属性读方法”和“属性写方法”的数据类型必须一致,也就是说:“属性读方法”的返回值与同名“属性写方法”第一个参数的数据类型必须一致:

如图中黄色和红色箭头所指向的数据类型必须一致。

 

4、定义“可读写成员变量属性”:

有时候我们想直接把一个“成员变量”同时定义为“成员属性”,譬如前面的例子所定义的“我的属性”也可以这样定义:

具体方法就是为该成员变量设置属性值为的“@属性变量”系统属性(系统属性是指以'@'字符开头的系统预定义属性)即可。

操作小提示:要想知道当前对象有哪些“系统属性”,在“属性名”列上输入'@'字符即可:

注意:这些系统属性,除了在本文档中提到的,一般用户无需了解。

此处定义的“我的属性”,与前面通过“属性读/写方法”定义的“我的属性”没有任何区别,同样可以在对象的属性表中使用:

那么问题来了,既然可以这么简单地定义成员属性,那么为什么还要那么麻烦去通过“属性读/写方法”来定义呢?

道理很简单:通过“属性读/写方法”来定义可以使用程序代码对属性的读/写操作进行具体控制,还可以进行一些额外的特定操作,而定义“成员 变量属性”就没办法达到这个目的了,本处两者效果一致只是一个特例。

 

5、定义“只读成员属性”和“只写成员属性”:

定义“只读成员属性”和“只写成员属性”很简单:

只提供了“属性读方法”的属性就是只读属性,只提供了“属性写方法”的属性就是只写属性

如果想对“只读成员属性”进行写操作,或者想对“只写成员属性”进行读操作,编译器都会报错:

如上图,在“测试类”中定义了名为“我的只读属性”的只读属性(未提供该名称的属性写方法)和名为“我的只写属性”的只写属性(未提供该名称的属性读方法),那么在黄色和红色箭头所指向处的代码在编译时都会报错。

可以通过此方式对属性的读写权限进行分别控制。

 

定义类成员事件

成员事件用来类对外发送通知时使用

一个很简单的例子:用作“按钮”的类必须在用户单击按钮时向外部发送“被单击”事件,用作“时钟”的类必须向外部定时发送“时钟周期”事件,等等。

类的其它三类“成员变量”、“成员属性”、“成员方法”都是被动接受来自外部的访问,而“成员事件”是主动向外部发送通知,这是两者之间的最主要不同。

 

1、定义“成员事件”:

插入一个方法,将其“类别”列设置为“定义事件”,然后保证其满足以下格式要求:

1、访问权限必须为“公开”;

2、不能为静态方法;

3、返回值必须为整数;

4、方法体必须为空。

事件定义方法对参数表没有要求,用户可以根据自己的需要随意定义。

譬如我们先前所定义的“电水壶类”中的“水烧开警告”事件:

 

2、在类中发送事件:

在类中的代码内,当需要发送事件时,直接调用该事件的“事件定义方法”即可,如前面例子中的:

当调用“事件定义方法”时,如果该事件定义方法上挂接了对应的“事件接收方法”(见下),会自动去调用该“事件接收方法”并返回其所返回的整数值,否则会直接返回整数值0。

 

3、接收其它类所发送过来的事件:

要想接收其它类所发送的事件,必须首先定义相应的事件接收方法,譬如以下代码在“测试类”中定义了一个“电水壶类”的对象:

想要接收其“水烧开警告”事件,需要如下操作:

鼠标右键单击“电水壶对象”的定义行:

选择其中的“添加电水壶对象的事件接收方法”菜单项:

再选择其中的“电水壶类_水烧开警告”,然后单击“添加”按钮,会自动在程序中插入对应的事件接收方法:

当然,你也可以自己手工创建并填写符合此格式的方法,效果是一样的。

查看上面所生成的“事件接收方法”,可以发现它的格式要求:

1、方法名称必须为:“事件定义方法所处类名”+下划线+“事件定义方法名称”;

2、不能为静态方法;

3、方法的第一个参数必须为固定的“来源对象”参数,其数据类型为发送事件的类,用作提供具体是哪个对象发送过来的事件;

4、方法的第二个参数必须为固定的“标记值”参数,其数据类型为整数,用作动态挂接事件时使用(见后);

5、方法的后续参数表必须与对应的“事件定义方法”一致,用作提供在事件定义方法所处类中发送事件(调用该事件定义方法)时所传递过来的具体参数值;

6、方法的返回值必须为整数,此返回值将被传递回在事件定义方法所处类中调用该事件定义方法的调用方。

一旦为类成员变量对象的“事件定义方法”定义了对应的“事件接收方法”,那么该事件就被自动挂接到了此接收方法上,在事件定义方法所处类中一旦调用该“事件定义方法”,此“事件接收方法”就会被自动调用。

具体例程请参见火山软件开发平台入门例程中的“火山面向对象设计”项目

附:这种特性是不是比其它编程语言更强大?不再是只有在被设计窗体上的窗口组件才能发送事件了,也不再需要为了让其能发送事件去开发类似“时钟”这样的哑窗口组件了。在火山中,任何代码位置处的对象均可以发送事件。

 

4、动态挂接其它类所发送过来的事件:

如前所述,一旦为类成员变量对象的“事件定义方法”定义了对应的“事件接收方法”,那么该事件就被自动挂接到了当前类中的对应“事件接收方法”上,但是其它代码位置处对象的事件是不会自动挂接到当前类中的,譬如下面代码:

在“测试方法”中定义了一个“电水壶类”的局部变量对象,此时该对象上的“水烧开警告”事件是不会自动挂接到当前类的“电水壶类_水烧开警告”事件接收方法上的。也就是说,当前类此时将无法接收到来自此“局部电水壶对象”的“水烧开警告”事件。

如果需要接收该局部变量对象的事件,必须调用“挂接事件”关键字明确挂接其事件到当前类:

挂接事件(局部电水壶对象)”语句被执行后,此“局部电水壶对象”的“水烧开警告”事件就被挂接到了当前类的“电水壶类_水烧开警告”事件接收方法上,以后当前类就可以接收到来自该对象的“水烧开警告”事件了。

在调用“挂接事件”关键字时可以额外再提供一个标记值参数,如:“挂接事件(局部电水壶对象,123)”,此时该“局部电水壶对象”一旦发送事件,事件接收方法的“标记值”参数将接收到此处所提供的标记值“123”,便于程序中对此事件进行特定处理。

 

三、“祖国您好!”

前面阐述了火山面向对象的应用机制,老规矩,我们来开发一个显示“祖国您好!”的程序。

选择“文件->新建->项目”菜单项:

在左侧树形框中选择“空白安卓程序”项目,在上部选择“空窗口”,在“项目名称”编辑框中输入项目的名称(随意),在“所处位置”编辑框中输入新建解决方案所处的文件目录(随意),在“解决方案名称”编辑框中输入所新建解决方案的名称(随意),然后点击确定新建一个解决方案

在此解释一下火山的“项目”和“解决方案”概念:

项目:记录用作生成目的程序(安卓平台下是“.APK”)的所有火山源代码程序的集合,并同时提供相关的编译时设置信息。

解决方案:记录一序列的相关项目集合,用作开发者将相关项目归类集中管理。

即,按被集合顺序:“火山源代码程序”->“项目”->“解决方案

前面新建解决方案时同时指定新建了一个安卓程序项目,该项目内创建了一个默认火山源代码程序文件:

鼠标右键单击“启动类”的定义行:

选择所弹出菜单中的“设计启动类的界面布局”菜单项:

注意:

1、名为“启动类”的类在整个项目中只能存在一个,用作标记用户程序的启动位置;

2、只有窗口类(直接或间接基础类为“窗口”的类)才能设计其界面布局。

以下为“启动类”的界面布局设计器界面:

选择左侧工具箱中的“按钮”组件,将其拖动到设计区域内:

选择设计区域内的“按钮1”,然后在右侧属性表中的“文本”属性内填入“我的按钮”文本:

点击“确认”按钮返回到程序设计界面,此时可以发现界面设计器自动在“启动类”中插入了一个数据类型为“按钮”名称为“按钮1”的成员变量,其具有一个名为“安卓.窗口.布局”属性,在此属性的属性值中记录了所有在界面设计器中对此按钮的设计内容。由于这些内容普通用户无需了解,所以其属性值默认处于“隐藏”状态:

为了便于程序与其相关数据的集中维护和查找,火山遵循“程序与数据集中”的原则。因此火山并没有将窗口类的界面布局数据与其程序分开存放,而是全部存放在窗口类自身的源代码中。在安卓平台中,具体就在窗口类及其中的“窗口组件类”(直接/间接基础类为“窗口组件”的类)成员变量的“安卓.窗口.布局”属性值中。

所以以上代码你不通过界面设计器自行手工录入也是可以的,不过比较繁琐。

按钮添加完毕后,我们现在要来接收此按钮的被单击事件,用作在按钮被单击时显示“祖国您好!”文本。

根据我们在前面所讲过的方法,右键单击“按钮1”成员变量,然后选择所弹出菜单中的“添加按钮1的事件接收方法”菜单项,选择其中的“按钮_被单击”事件:

然后点击“添加”按钮,将在“启动类”中自动插入如下“事件接收成员方法”:

在“返回 (0)”语句前按下“Insert”快捷键插入一个空语句行,然后输入以下代码:

提示信息框 ("祖国您好!")

还记得首拼输入法吗?不用敲汉字输入“提示信息框”那么麻烦,直接输入此文本的首拼字母“tsxxk”然后选择对应列表项就可以了(程序中所需要输入的其它中文文本都可以这样输入)。

至此,我们第一个程序开发完毕。在运行程序之前,必须首先做如下准备工作(以后不再累述):

1、电脑上必须已经安装了JDK和安卓ADK软件开发包,下面是它们的最新下载地址:

JDKhttp://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

ADKhttps://developer.android.com/studio/index.html (下载后面的命令行工具即可)

下载安装完毕后,请执行菜单项“工具->选项->安卓管理器->全局”,然后填写其中的对应选项。也可以不填写,此时系统将根据相关环境变量自动搜寻。

如果不愿意下载前面的内容,您也可以选择下载我们整合好的相关JDK和ADK包,然后直接解压到火山平台安装目录的“plugins\vprj_android”子目录下即可(此时请保持上图箭头所指向的属性项为空)。

2、强烈推荐直接使用安卓真机测试,速度快而且直接面对真实应用环境。此前需要先启用测试用安卓手机的USB调试模式(请查询该手机的用户手册),在电脑上安装该手机的驱动程序(手机厂商提供或使用通用驱动程序),然后使用USB连线将其连接到电脑,最后在手机上授权当前电脑对该手机的USB调试许可即可。
 

运行前的准备工作做完后,按下“F5”快捷键启动程序然后单击“我的按钮”看效果吧:

 

未完待续,请保持关注......