翻译 ActionScript 3: Dynamic Classes

原文地址

在java里,如果你从一个特定的类创建了一个对象,那么你只能使用这个类定义了的属性和方法,举例:
class Person {
public String name;
}
你只能对其name属性进行操作:
Person p = new Person();
p.name = “Joe”;
System.out.println(p.name);

ActionScript称这种类为封闭的,和这种类相对的另外一种类叫做:动态类,允许以编程的方式在运行时给类增加新的属性和行为只需要动态的将神奇的关键字加到类的定义里。
dynamic class Person {
var name:String;
}
现在我们往类型为Person的对象里动态的增加属性age和函数printMe:
Person p= new Person();
p.name=”Joe”;
p.age=25;
p.printMe = function () {
trace (p.name, p.age);
}
p.printMe(); // Joe 25
但是你也不是完全的自由,你只能动态的增加公共的属性和方法,当然,天下没有免费的午餐,静态类在内存的使用上显得更高效一点,这是因为它不需要建立Hash表来存储在在编译时未知的属性和函数。

Blogspot SEO(Search Engine Optimization)

1.Google的Googlebot在抓取页面的时候,页面标题Title是一个非常重要的参数,Title在搜索结果中是为结果条目的标题,但是在blogspot中默认的文章标题与网站标题位置是颠倒的,每一篇文章页面的title都是以博客的标题为前缀的,这样对搜索引擎来讲不是很友好,你的文章的关键字就得不到突出,也会影响到你的搜索排名情况,那怎么解决呢?
在后台修改模板的HTML代码,将
<title><data:blog.pageTitle/></title>

修改为:
<b:if cond='data:blog.pageType == "index"'>
<title><data:blog.title/></title>
<b:else/>
<title><data:blog.pageName/> - <data:blog.title/></title>
</b:if>


2.还有就是blogspot的网页地址生成规则的把握,Blogger发表中文文章标题的时候永久链接的格式为:yourname.blogspot.com/年/月/blog-post_文章ID.hmtl,如果我们需要将关键字出现在文章永久链接里面的话,比如我想发布一篇《你好美女》的文章,可以在发布文章的时候先用英文标题:hello beauty,等文章发表成功之后再将英文标题修改为中文标题:你好美女,这样,最后文章的标题就是:yourname.blogspot.com/2008/09/hello-beauty.html。

Google 网站管理员中心 简介

Google 网站管理员中心 是提供给网站管理员使用的,它可以帮助您回答有关抓取和编制索引的问题,向您介绍改善和提高网站流量的产品和服务,从而增进与访问者之间的联系。
我就试着使用了一下,首先可以将自己的网站添加到网站列表中,这样你就可以查看你的网站在google索引中的情况了。
然后你就可以为你的网站添加sitemap和对你网站进行验证。
由于blogspot无法自己上传sitemap,所以一开始觉得没有办法,后来上网搜索了一下,可以使用blogger自带的atom.xml或rss.xml来当作sitemap文件,
地址是:你的网站地址/atom.xml
目前验证有两种方式,一是上传指定文件名的静态html文档,二是加入指定的meta,这里选取了第二种方式,

验证的目的是为了确认你是该网站的管理员,验证后你就可以查看你网站的一些信息了。
比如你网站是否被索引到,你所提交的sitemap是不是被索引了之类的。

Flex数组解惑

前几天对如下的数组初始化方式一直感到疑惑,不明其原理,今天终于豁然开朗。
private var students:Array = new Array({name:"luke",age:22},{name:"jane",age:18});
或者 var students:Array =[{name:"luke",age:22},{name:"jane",age:18}];

这里数组中的{name:"luke",age:22}和{name:"jane",age:18}其实都是一个Object对象,也就是这个数组中的每一个成员都是一个Object对象。

Associative arrays (关联数组)

关联数组有时候也称为"哈希"或"映射",由key和value组成。
关联数组是key和value的无序集合。

在ActionScript3中引入了名为"字典"的高级关联数组。
字典是 flash.utils 包中 Dictionary 类的实例,使用的键可以为任意数据类型,
但通常为 Object 类的实例。即字典的key不局限于 String 类型的值。

关联数组的key分类有以下2种。

1.key为字符串
在 as3中有两种创建关联数组的方法。

a.使用 Object 构造函数
Object 类的实例在功能上等同于关联数组。

如:
var luke:Object = {name:"Luke", age:22};
trace(luke["name"], luke["age"]);
// 输出:luke 22
//其实这些key和value的对在对象中是其属性和属性值

如在声明数组时不需要初始化,则以[] 或者 .的方式 添加值。
如:
var luke:Object = new Object();
luke["name"] = "Luke";
luke.age = "22";

b.用 Array 构造函数,如果将关联数组声明为 Array 类型,则将无法使用对象文本初始化该数组。

var luke:Array = new Array();
monitorInfo["type"] = "Flat Panel";
monitorInfo["resolution"] = "1600 x 1200";
trace(monitorInfo["type"], monitorInfo["resolution"]);
// 输出: Flat Panel 1600 x 1200

用 Array 构造函数创建关联数组没有什么优势。即使使用 Array 构造函数或 Array 数据类型,
也不能将 Array 类的 Array.length 属性或任何方法用于关联数组。
最好将 Array 构造函数用于创建索引数组。

即不赞成用array做字典以及哈希组织数据。

2.key为对象
用 Dictionary 类创建使用对象而非字符串作为键的关联数组。

如,考虑这样一个应用程序,它可根据 Sprite 对象与特定容器的关联确定 Sprite 对象的位置。
可以使用 Dictionary 对象,将每个 Sprite 对象映射到一个容器。

如下例子:

import flash.display.Sprite;
import flash.utils.Dictionary;

var groupMap:Dictionary = new Dictionary();

// 作为键名的对象
var spr1:Sprite = new Sprite();
var spr2:Sprite = new Sprite();
var spr3:Sprite = new Sprite();

// 用作值的对象
var groupA:Object = new Object();
var groupB:Object = new Object();

// 在字典中创建新的键-值对。
groupMap[spr1] = groupA;
groupMap[spr2] = groupB;
groupMap[spr3] = groupB;

if (groupMap[spr1] == groupA)
{
trace("spr1 is in groupA");
}
if (groupMap[spr2] == groupB)
{
trace("spr2 is in groupB");
}
if (groupMap[spr3] == groupB)
{
trace("spr3 is in groupB");
}

设计模式之Strategy

Strategy中文名叫做策略,计谋,一听就知道是为实现某一需求而所使用的方法,相对于编程中的对象也就是对象所表现出来的行为。
Strategy模式主要用来将算法实现从类中分离出 来,并封装在一个单独的类中。更简单的说,对象与其行为(behaviour)这本来紧密联系的两部分被解耦,分别放在了两个不同的类中。这使得对同一个 行为,可以方便的在任何时候切换不同的实现算法。而通过对策略的封装,为其提供统一的接口,也可以很容易的引入新的策略。

想起这种设计模式主要是因为最近在使用as3实现panel的几种常见布局,由于布局的算法和容器本身是分离的,使用了策略的设计模式。

为了方便我用GNU的java实现的Layout给大家介绍一下,具体代码可以使用
来进行搜索相关的类。
AWT的LayoutManager,是 Strategy模式的一个例子。对于GUI而言,每个组件(Component)在容器中(Container)的排放是需要遵循一定的算法的。通常的方法是使用绝对坐标,就像VB,Delphi之类的工具所作的那样,记录每个组件在容器中的位置。这当然会带来一些问题,比如在窗体缩放的时候,就需要手工编码改变组件的大小和位置,以使得原来的比例得以保存。而在AWT中,引入了布局管理器(LayoutManager)的概念,使得布局的方法大大丰富,编码过程也变得简单。
一个容器,比如Applet,Panel等,仅仅记录其包含的组件,而布局管理器中封装了对容器中组件进行布局的算法,具体地说,就是指明容器中组件的位置和尺寸的大小。通过布局管理器,你只需要确定想放置的组件间的相对位置即可,这一方面简化编码,另一方面也有助于实现软件的平台无关性。
每一个容器均有一个布局管理器,当容器需要布置它的组件时,它调用布局管理器的方法布置容器内的组件。LayoutManager2继承于LayoutManager,提供更为细致的布局功能,它可以让布局管理器为组件加上约束条件已确定组件如何被布置。例如,为了确定组件被摆放在边框内的位置,BorderLayout在它的组件上加上方向指示。
特别的,通过实现LayoutManager或者LayoutManager2接口,可以很容易实现自定义的布局策略。
回到模式的话题上来,如果有几个很相似的类,其区别仅仅是在个别行为上的动作不同,这时候就可以考虑使用Strategy模式。这样,通过策略组合,将原来的多个类精简为一个带有多个策略的类。这很符合OO设计的原则:找到变化的部分,并将其封装起来!Strategy模式同样的为子类继承提供了一个好的替代方案,当使用继承机制的时候,行为的改变是静态的,你指能够改变一次--而策略是动态的,可以在任何时候,切换任何次数。更为重要的是,策略对象可以在不同的环境中被不同的对象所共享。以布局管理器为例,虽然每一个容器只有一个布局管理器,但是一个布局管理器可以为多个容器工作。
Strategy模式也有一些缺点,比如,应用程序必须知道所有的策略对象,并从中选者其一。而且在策略对象被使用的时候,它和Context对象之间通常是紧耦合的,Context对象必须为策略对象提供与具体算法相关的数据或者其它的东西,而这些数据的传递可能并不能够风装载抽象地策略类中,因为并不是所有的算法都会需要这些数据的。另外,因为策略对象通常由应用程序所创建,Context对象并不能够控制Strategy的生命期,而在概念上,这个策略应该从属于Context对象,其生命期不应该超出 Context的范围对象。
通常的,Strategy很容易和Bridge模式相混淆。确实,他们有着很相近的结构,但是,他们却是为解决不同的问题而设计的。Strategy模式注重于算法的封装,而Bridge模式注重于分离抽象和实现,为一个抽象体系提供不同的实现。

Tomcat 远程调试

window:tomcat/bin/startup.bat
linux:tomcat/bin/startup.sh
文件中加入:
SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Djava.compiler=NONE
-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000
其中8000为调试的端口号

Java自定义Annotation

Annotation注解(也称Meta Data元数据)为我们在代码中添加信息提供一个形式化的方法,是我们在后面的某个时刻方便的使用这些数据。
JavaSE5中自带了一些Annotation,可以分为两类,
标准注解,目前Java自带的有三个@Override,@Deprecated,@Suppress Warning
元注解
元注解是用来注解其他Annotation的,用的比较多的有两个
@Target 表示该注解可以用于什么地方。其取值的类型为java.lang.annotation.ElementType枚举类型
@Retention 表示需要在什么级别保存该注解,取值为RetentionPolicy枚举类型


整个Annotation的使用过程可以分成三块,Annotation的定义,Annotation的使用,和Annotation的处理器。
1.首先我们可以看一下如何定义一个Annotation
package com.luke.hello;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//用于域的声明
@Target(ElementType.FIELD)
//VM在运行期间也会保存annotation的信息,所以可以使用反射机制来读取之
@Retention(RetentionPolicy.RUNTIME)
public @interface Hello {
public String echo() default("Hello,I am a field!");
}


2.我们将这个刚刚定义的Annotation拿来使用
package com.luke.test;
import com.luke.hello.Hello;
public class Book {
@Hello(echo
="Hello,I am the name of the book!")
public String name;
}

3.写一个处理器类来对Annotatin进行处理,这里要使用到Java的反射机制了呢
package com.luke;

import java.lang.reflect.Field;
import com.luke.hello.Hello;
import com.luke.test.Book;

public class BookFileldTracker {
public static void trackBook(Class<?> cl){
for(Field f:cl.getDeclaredFields()){
Hello h
= f.getAnnotation(Hello.class);
if(h!=null)
{
System.out.println(h.echo());
}
}
}
public static void main(String[] args){
trackBook(Book.
class);
}
}

foucusOut事件

focusOut事件是指焦点离开某控件时触发的事件,这个比较简单,只是举个比较简单的例子:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="initEvent()">
<mx:Script>
<![CDATA[
public function initEvent():void
{
panelWidth.addEventListener(FocusEvent.FOCUS_OUT,focusOut);
this.addEventListener(MouseEvent.CLICK,mouseClick);
}
public function focusOut(event:FocusEvent):void
{
panel.width = parseInt(panelWidth.text,10);
}
public function mouseClick(event:MouseEvent):void
{
panelWidth.focusManager.deactivate();
}
]]>

</mx:Script>
<mx:Panel id="panel">
</mx:Panel>
<mx:Label text="宽" />
<mx:TextInput id="panelWidth"/>
</mx:Application>


此例子中涉及了Application 表单的 creationComplete 事件,这个一般用来对事件的注册进行初始化。
还有就是deactivate可以使控件失去焦点。(focusManager还需学习)

Flex反射机制

这里用到一个类flash.utils.getDefinitionByName,其作用是返回由name参数指定的类的对象引用,然后我们就可以根据这个类的类引用实例化该类。
不过有个缺陷, 使用getDefinitionByName方法获得的类必须是在发布的时候被编译到swf文中的,否则就会报错:"ReferenceError: Error #1065: 变量 <类的名字> 未定义。"
且即使你import了某个类,是没有用的,需要定义一个这个类的引用才可以解决问题。

Flex之DataGrid

最近一直在使用ActionScript3进行编码,也学到了不少的新的知识,虽然觉得Flex3现在还不是很成熟,但我相信,Flex4出来后应该还是有不错的前景的。

在Flex中,控件既可以使用mxml的标记来描述,也可以写在ActionScript的代码里,但是归根结底,mxml最终还是被编译成as代码的,写成mxml只是为了编程的方便而已。

今天我就来谈一谈DataGrid这个控件吧。

DataGrid 控件提供以下功能:
1.列可以具有不同宽度或同一固定宽度
2.用户可以在运行时调整其尺寸的列
3.用户可以在运行时对其重新排序的列
4.可选择自定义列标题
5.对任意列使用自定义项目渲染器以显示除文本之外的数据的功能
6.支持通过单击列对数据进行排序

一个DataGrid控件既可以使用mxml标签的形式书写,也可以使用as3的代码写出来。

如下面所示,是使用mxml标签来进行描述的,其中medals是个XML类型的对象。
<mx:DataGrid id="dg" dataProvider="{medals.children()}">
<mx:columns>
<mx:DataGridColumn dataField="@name" headerText="国家"/>
<mx:DataGridColumn dataField="@gold" headerText="金牌"/>
<mx:DataGridColumn dataField="@silver" headerText="银牌"/>
<mx:DataGridColumn dataField="@copper" headerText="铜牌"/>
<mx:DataGridColumn dataField="@total" headerText="总计"/>
</mx:columns>
</mx:DataGrid>


如果使用as3的代码怎么写呢,首先得写在一个函数里。
public function genDataGrid():void
{
var dg:DataGrid = new DataGrid();
dg.dataProvider = medals.children();
var countryColumn:DataGridColumn = new DataGridColumn();
countryColumn.dataField = "@name";
countryColumn.headerText = "国家";
var goldColumn:DataGridColumn = new DataGridColumn();
goldColumn.dataField="@gold";
goldColumn.headerText = "金牌";
dg.columns = dg.columns.slice(0,0).concat(countryColumn).concat(goldColumn);
panel.addChild(dg);
}