请先复制以下代码,在 PDE 中运行。
// Modify by akb4q
// Learning Processing
// Daniel Shiffman
// http://www.learningprocessing.com
// Example 7-3: Bouncing ball with functions
//实例声明
BouncingBall jsj;
BouncingBall hqm;
//程序初始
void setup() {
size(640, 360);
smooth();
//实例初始化
jsj = new BouncingBall(100, 100, 2.5, 1, 100);
hqm = new BouncingBall(100, 100, 1, 1, 50);
}
//程序运行
void draw() {
background(255);
//调用对象方法
jsj.move();
jsj.display();
hqm.move();
hqm.display();
}
// 类定义
class BouncingBall {
// 变量声明
float locationX; // 位置
float locationY;
float xSpeed; // 速度
float ySpeed;
int diameter; // 大小
// 构建 constructor
BouncingBall(float _locationX, float _locationY, float _xSpeed, float _ySpeed, int _diameter) {
// 把临时变量赋值给变量
locationX = _locationX;
locationY = _locationY;
xSpeed = _xSpeed;
ySpeed = _ySpeed;
diameter = _diameter;
}
// 方法 method
void move() {
// Change the x location by speed
locationX += xSpeed;
locationY += ySpeed;
// If we’ve reached an edge, reverse speed
if ((locationX > width-diameter/2) || (locationX < 0+diameter/2)) {
xSpeed *= -1;
}
if ((locationY >= height-diameter/2) || (locationY <= 0+diameter/2)) {
ySpeed *= -1;
}
}
void display() {
stroke(0);
fill(175);
ellipse(locationX, locationY, diameter, diameter);
}
}
伪代码 pseudo-code 作为一种方法,可以有效的让程序架构思路清晰,往往在写代码之前,把整个架构用伪代码的方式写下来,但不是用于执行,而是让自己明了。对于初学者来说可以先有这个意识,但简短的任务,往往直接就上手了。
用伪代码来写一下以上的代码过程:
1.声明江山娇和红旗漫,做为两个弹球
2.江山娇大个一点,红旗漫瘦一点
3.江山娇运动,红旗漫也运动,但根据体型不同,可能移动的速度也有所不同. 当他们碰壁的时候,往相反的方向运动
4.他们就是这么虚无的在平面国里移动
对于程序员来说,他们总是用上帝视角看待世界。
Object-oriented Programming (OOP) 是这种上帝视角的体现。不仅俯瞰整个类 class的世界,并且从内部去创建实例 Object。
人类有那些共有的特征呢?有头有脚,吃喝拉撒,直立行走,能跑能跳。我作为人类,所以我是人类的实例。比如我的身高、体重、等等这些都是我的参数。正是这些不同的参数造成了人类的多样性。 再比如车子,各种型号、牌子、功能等等,但基本结构是一个样的,都有四个轮子和一个车身。某个牌子的车子的某个型号就是汽车的实例。
为了更有效且方便地调用类,就有了 OOP 这种编程思路:
传统的程序设计主张将程序看作一系列函数的集合,或者直接就是一系列对电脑下达的指令。面向对象程序设计中的每一个对象都应该能够接受数据、处理数据并将数据传达给其它对象,因此它们都可以被看作一个小型的“机器”,即对象。 wikipedia
补充:我个人把 OOP 翻译为“实例导向”,但你在很多地方会看到“面向对象”,知道实同一件事就可以了。 翻译的问题很麻烦,但每个人应该有自己理解方式和态度。
Java 其实是一种 OOP 型的语言,可以把任何看作是类的实例。以后你会逐渐发现这点。
在深入类之前,我们很快的看一下类在整个主程序中的使用方法。
// Step 1. Declare an object. 实例声明
BouncingBall jsj;
void setup() {
// Step 2. Initialize object. 处始化实例
jsj = new BouncingBall();
}
void draw() {
background(255);
// Step 3. Call methods on the object. 调用实例的方法
jsj.move();
jsj.display();
}
- 在程序开头处声明实例
- 在
setup()
处初始化实例,使其成为实例 - 在
draw()
里调用实例的方法
我们从语法上可以做比一个比较:
int a; // 变量声明
BouncingBall jcj; // 实例声明
你会发现变量声明就是在创建某种数据类型的实例。声明a
做为一个整数,同理BouncingBall
是类 class,而jsj
是实例 Object,也就是我们创建的对象。实例名可以随便取,和变量名一样,但惯例是小写。
在 setup() 里,我们要把具体的 arguments 给进去。
//初始化对象
jcj = new BouncingBall(100, 100, 2.5, 1, 100);
当程序帧运行到这的时候,程序会跳到类的程序块部分,这个类取名为 “BouncingBall”, 通常类名会首字母大写或者全部大写,以区别对象的小写。这是类的命名惯例。
jsj.move();
jsj.display();
在实例名后通过.方法名()
的语法调用方法。会发现方法和函数类似。但是也请注意关于方法 method 和函数 function 的区分。在类的语境下,我们惯例称为方法 method 。
整个类程序块由这四部分组成
- 定义取名
- 变量声名
- 函数构建
- 创建方法
// 类定义
class BouncingBall { // 定义取名
// 变量声明
float locationX; // 位置
float locationY;
float xSpeed; // 速度
float ySpeed;
int diameter; // 大小
// 构建 constructor
BouncingBall(float _locationX, float _locationY, float _xSpeed, float _ySpeed, int _diameter) {
// 把临时变量赋值给变量
locationX = _locationX;
locationY = _locationY;
xSpeed = _xSpeed;
ySpeed = _ySpeed;
diameter = _diameter;
}
// 方法 method
void move() {
// Change the x location by speed
locationX += xSpeed;
locationY += ySpeed;
// If we’ve reached an edge, reverse speed
if ((locationX > width-diameter/2) || (locationX < 0+diameter/2)) {
xSpeed *= -1;
}
if ((locationY >= height-diameter/2) || (locationY <= 0+diameter/2)) {
ySpeed *= -1;
}
}
void display() {
stroke(0);
fill(175);
ellipse(locationX, locationY, diameter, diameter);
}
}
首先 class 小写,类名应含有大写或全部大写,这之前讲过。
class BouncingBall{
}
用大括弧{}
给出程序块的空间。
float locationX; // 位置
float locationY;
float xSpeed; // 速度
float ySpeed;
int diameter; // 大小
类所独用的变量,同时也可以作为实例的方法,在主程序中被调用。
print(jsj.locationX);
这点很重要,因为 OOP 的目的就是让数据可以在不同的模块中流通,这个模块就是类。
我们把构建 constructor 理解为是类的接口,设置形参 parameter, 用于在实例初始化的时候可输入具体的实参 arguments,给变量赋值。
// 构建 constructor
BouncingBall(float _locationX, float _locationY, float _xSpeed, float _ySpeed, int _diameter) {
// 把临时变量赋值给变量
locationX = _locationX;
locationY = _locationY;
xSpeed = _xSpeed;
ySpeed = _ySpeed;
diameter = _diameter;
}
和自定义函数的语法类似,如果只要求方法执行,不回报值的情况下,用 void 打头
void move(){
}
void display(){
}
实例导向,可以让你通过类创建不同的实例,并且赋予不同的实例以特征,和函数一样可被重复调用和优化。OOP 是一种写代码的思路和理解系统和看待世界的方式。