Think in ActionScript 3.0Ⅰ
2009-05-30 12:08:08 来源:WEB开发网1.类的由来
1.1
struct Student {
int id;
char[20] name;
} student;
main() {
// 可以使用“对象名.属性” 的方式来操作数据
student.id = 5;
student.name = “ZhangSan”;
}
1.2 从结构体到类的演化(C —— C++)
| |
struct 结构名 { | struct 结构名 { |
class Student {
private:
int id;
char[20] name;
public:
void gotoSchool() {}
}
C++ 最初的名字叫做“C with class”(带类的C),经过长时间的发展,最终敲定将其命名为 C++,“++”表示加一操作,代表它比 C 语言更进步,更高级。
2.封装(Encapsulation)
2.1 封装的概念
class Father {
private var money:int = 10000000;
public takeMoney():int {
money -= 100;
return 100;
}
}
定义名为 Father 的类(一个有钱的父亲),类中有一个成员变量 money 它的访问权限为 private 意思是说 money 是 Father 私有的,private 是指只有在这个类里面才能访问,出了这个类就无法访问该成员了,稍后会有关于访问权限更多的解释。
2.2 封装的好处
2.3 封装的目的
(1)隐藏类的实现细节;
(2)迫使用户通过接口去访问数据;
(3)增强代码的可维护性。
2.4 封装的技巧
class Person {
private var _age:int;
public function get age():int {
return _age;
}
public function set age(a:int):void {
if (a < 0) {
trace("age 不能小于 0!");
return;
}
_age = a;
}
}
首先,实例化出该类的对象 var person:Peron = new person()。如果要设置成员变量 _age 就要通过调用 set age() 来实现:person.age = 5。实际上,我们是在调用 set age(5) 这个方法,但是由于有了 set 修饰符,操作的方法就是给对象的属性赋值,但实际上是在调用函数。但是如果这么写 person.age = -20,这样合理吗?一个人的年龄等于 -20 岁,显然不对。因此在调用 set age() 方法中,可以进行一下判断,如果给的参数不对就发出提示,这项工作只能由函数来完成,这是属性没办法到的。
回想一下封装的定义,它的用意就在于数据(成员变量)是核心,不可以随随便便去改,要想改只能去调用公开的函数,而在函数可以进行各种判断,保证对数据的修改是经过思考的,合理的。
说到 get/set 现在去看看 ActionScript 3 是怎么做的。我们知道 TextField 类有一个 text 属性,查看帮助文档,会看到:
text 属性 实现
|
3. 访问控制(Access Control)
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
(1)private:仅当前类可访问,称为私有成员;
(2)internal(默认):包内可见,在同一文件夹下可访问(如果不写权限修饰符,默认权限也是它);
(3)protected:子类可访问,与包无关。如果不是该类的子类,那么 protected 和 private 是一样的;
(4)public:完全公开。任何地方、任何对象都可以访问这个类的成员。
4. 继承(Inheritance)
4.1 继承的概念
包 flash.display 类 public class Sprite 继承 Sprite→DisplayObjectContainer→InteractiveObject→DisplayObject→EventDispatcher→Object 子类 |
4.2 TestPerson.as —— 属性与方法的继承
package {
public class TestStudent {
public function TestPerson() {
var student:Student = new Student();
student.name = "ZhangSan";
student.age = 18;
student.school = "114";
trace(student.name, student.age, student.school);
}
}
}
class Person {
private var _name:String;
private var _age:int;
public function get name():String{
return _name;
}
public function set name(n:String):void {
if (n == "") {
trace("name 不能为空!");
return;
}
_name = n;
}
public function get age():int {
return _age;
}
public function set age(a:int):void {
if (a < 0) {
trace("age 不能小于 0!");
return;
}
_age = a;
}
}
class Student extends Person {
private var _school:String;
public function get school():String {
return _school;
}
public function set school(s:String):void {
_school = s;
}
}
注意,package 中包的是用来测试的类,为了演示方便Person 和 Student 跟这个测试类放在了一个 as 文件中。
4.3 TestExtends.as —— 继承的限制
package {
public class TestExtends {
public function TestExtends() {
new Son();
}
}
}
class Father {
private var money:int = 1000000;
public var car:String = "BMW";
private function work():void {
trace("writing");
}
}
class Son extends Father {
public var bike:String = "YongJiu";
// 没有继承因此谈不上重写
private function work():void {
trace("studying");
};
function Son (){
trace(bike);
trace(car);
//trace(money); // private 的属性不能被继承
work();
}
}
这个例子要演示哪些属性或方法不能被继承。本例中定义了一个 Father 类,其中包括 private 的money 属性,public 的 car 属性和 private 的 work() 方法。
4.4 内存分析
(1)heap 堆:存放 new 出来的对象;
(2)stack 栈:局部变量;
(3)data segment 数据段:静态变量和字符串常量;
(4)code segment 代码段:存放代码。
4.5 this 和 super 关键字
4.5.1 TestSuper.as —— this 和 super 以及 override
package {
public class TestSuper {
public function TestSuper() {
new Extender();
}
}
}
class Base {
public var name:String;
public var age:uint;
//function Base(){
// 即使不写构造函数,系统也会自动添加的无参构造函数
//}
public function work():void {
trace("Writing!");
}
}
class Extender extends Base {
//public var name:String; // name 属性已从父类继承,不能重复定义
function Extender() {
// super(); // 即使不写 super(),系统也会添加的无参的 super();
super.work();
this.work();
}
override public function work():void {
trace("Programming!");
}
}
这个例子演示了 this 与 super 关键字的使用,以及重写(override)的概念。
何时使用重写呢?当我们对父类的方法不满意、或者同样的一个方法对于两个类来说实现的功能不相同时,就要考虑重写,把父类的方法冲掉,让它改头换面。
下面我们看一下内存图中,this 和 super 各代表着什么。
4.5.2 this 和 super 的内存分析
4.5.3 TestThis.as —— 用 this 区分局部变量与成员变量
package {
public class TestThis {
public function TestThis() {
var p:Person = new Person();
p.setInfo("ZhangSan", 20);
}
}
}
class Person {
private var name:String;
private var age:int;
public function setInfo(name:String, age:int) {
this.name = name;
this.age = age;
}
}
本例中就是用 this.name 指定是成员变量 name,而非传进来的局部变量的 name。age 也是如此。下面请看内存分析。
4.6 初始化顺序
package {
public class TestSandwich {
public function TestSandwich() {
new Sandwich();
}
}
}
class Water {
//static var w = trace("static water");
function Water() {
trace("Water");
}
}
class Meal {
//static var w = trace("static meal");
function Meal() {
trace("Meal");
}
}
class Bread {
function Bread() {
trace("Bread");
}
}
class Cheese {
function Cheese() {
trace("Cheese");
}
}
class Lettuce{
function Lettuce() {
trace("Lettuce");
}
}
class Lunch extends Meal {
function Lunch() {
trace("Lunch");
}
}
class PortableLunch extends Lunch {
//static var w = trace("static lunck");
function PortableLunch() {
trace("PortableLunch");
}
}
class Sandwich extends PortableLunch {
var bread:Bread = new Bread();
var cheese:Cheese = new Cheese();
var lettuce:Lettuce = new Lettuce();
//static var good = trace("static sandwich");
function Sandwich() {
trace("Sandwich");
}
}
测试类很简单只有一句:new Sandwich()。构造出 Sandwich 类一个实例。
Bread
Cheese
Lettuce
Meal
Lunch
PortableLunch
Sandwich
我们看到,最先打印出来的是 Bread, Cheese, Lettuce。这是 Sandwich 类的三个成员变量,可见在调用构造函数之前,要新将该类的成员变量构造出来,然后再去构造这个类本身。
static water
static meal
static lunck
static sandwich
Bread
Cheese
Lettuce
Meal
Lunch
PortableLunch
Sandwich
我们看到,所有静态的成员都先于非静态成员变量被构造出来!最上面有一个 Water 类,虽然没有地方会用到它,但是它也被打印出来了。结论是:当类被加载时静态的属性和方法就会被初始化。注意,什么叫类被加载时?这是指类被加载到内存里面。可见,我们整个这个 as 文件中的所有类都被加载到了内存中了,只要这个类被读入到内存中,那么它的所有静态成员就会被初始化。
4.7 静态属性与方法
4.7.1 static的概念
4.7.2 TestStatic.as —— static 属于这个类,不属于该类实例
package {
public class TestStatic {
public function TestStatic() {
var b:Ball = new Ball();
// 静态属性或方法属于这个类,而不属于该类对象,只能用类名引用
// b.sMethod();
// trace(b.color);
Ball.sMethod();
trace(Ball.color);
}
}
}
class Ball {
public var xpos:Number = 300;
public static var color:uint = 0xff0000;
public function changeColor():void {
color = 0;
}
public static function sMethod():void {
trace("I'm a static Method");
//trace(xpos); // 静态方法中不能调用非静态成员变量
//changeColor(); // 静态方法中不能调用非静态成员函数
}
}
在 Ball 这个类中有一个静态属性 color,一个静态方法 sMethod()。注意这条原则:静态属性与方法属于这个类,而不属于该类的实例。在 sMethod 中不能出现非静态的成员变量或方法。反之可以,在非静态的成员变量或方法中可以调用静态的成员变量或方法。
4.7.4 单例模式(Singleton Pattern)
package {
public class Singleton {
static private var instance:Singleton;
public function Singleton(singletonEnforcer:SingletonEnforcer) {}
public static function getInstance():Singleton {
if (instance == null) {
instance = new Singleton(new SingletonEnforcer());
}
return instance;
}
}
}
class SingletonEnforcer { }
这里用 SingletonEnforcer 类作为 Singleton 类构造函数的参数,由于这两个类放在一个 as 文件中,instance这个类只能被 Singleton 访问到,保证其它类得不到 SingletonEnforcer 的实例,用这种方法达到私有构造函数的作用。
Tags:Think in ActionScript
编辑录入:爽爽 [复制链接] [打 印]- ››include指令与<jsp:include>动作的区别
- ››Intent和IntentFilter详解
- ››thinkphp上传错误解决方法
- ››ActionScript 2.0中的! 逻辑 NOT 运算符
- ››Interface继承至System.Object?
- ››input按钮在IE浏览器的兼容
- ››ActionScript 3.0 性能方面优化小知识整理收集
- ››Intent调用大全
- ››IntentService实现原理及内部代码
- ››Internet Explorer 无法打开
- ››Intel和Nokia宣称MeeGo将比Android更加开放且方便...
- ››innerText、outerText、innerHTML、outerHTML的区...