代码如下:
代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
>
<LinearLayout
android:id="@+id/linearlayout_test_1"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff00ff00"
android:background="#aa331155"
android:layout_weight="1"
android:textSize="18sp"
android:text="Microsoft"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffff0000"
android:background="#aa117711"
android:layout_weight="1"
android:textSize="18sp"
android:text="Apple"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff0000ff"
android:background="#aa774411"
android:layout_weight="1"
android:textSize="18sp"
android:text="Google"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/linearlayout_test_2"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff00ff00"
android:background="#aa331155"
android:layout_weight="1"
android:textSize="18sp"
android:text="Microsoft"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffff0000"
android:background="#aa117711"
 
; android:layout_weight="1"
android:textSize="18sp"
android:text="Apple"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff0000ff"
android:background="#aa774411"
android:layout_weight="1"
android:textSize="18sp"
android:text="Google"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/linearlayout_test_3"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff00ff00"
android:background="#aa331155"
android:layout_weight="1"
android:textSize="18sp"
android:text="Microsoft"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffff0000"
android:background="#aa117711"
android:layout_weight="1"
android:textSize="18sp"
android:text="Apple"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff0000ff"
android:background="#aa774411"
android:layout_weight="1"
android:textSize="18sp"
android:text="Google"
/>
</LinearLayout>
</LinearLayout>
和:
代码如下:
package com.android.explorer;
import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
public class LinearLayoutTest extends Activity {
@Override
public void onCreate(Bundle
savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.linearlayout_test);
LinearLayout one = (LinearLayout) findViewById(R.id.linearlayout_test_1);
one.setOrientation(2012);
LinearLayout two = (LinearLayout) findViewById(R.id.linearlayout_test_2);
two.setOrientation(Integer.MAX_VALUE);
LinearLayout three = (LinearLayout) findViewById(R.id.linearlayout_test_3);
three.setOrientation(Integer.MIN_VALUE);
}
}
用Enum代替整数集
其实很简单,用Enum(枚举)就可以很方便的解决这个问题,使用起来也不比定义整数集繁琐,同样的可读。另外的优点就是,它的封装更好,最重要的是它会在编译时被检查。因为Java是一种Strong Type,也就是说在编译时,编译器会对所有原型类型和参数类型进行检查,如果类型不对,并且没有强制转型的,就会报出编译错误,当然编译器所支持的自动转型除外。比如一个需要int,而传的参数是long,虽然都差不多,没有溢出等,但还是会有编译错误。
所以,如果LinearLayout使用Enum,就像这样定义:
代码如下:
public class LinearLayout extends ViewGroup {
private Orientation mOrientation;
public enum Orientation {
HORIZONTAL, VERTICAL
};
public void setOrientation(Orientation dir) {
mOrientation = dir;
}
}
然后这样使用:
代码如下:
import android.widget.LinearLayout;
LinearLayout.setOrientation(Orientation.HORIZONTAL);
LinearLayout.setOrientation(Orientation.VERTICAL);
那么,开发者就不会用错了,因为首先,它看到setOrientation所需要的参数是一个Orientation的枚举类型,就会自然的传送Orientation中定义的类型;另外,如果传其他的值,比如0或者1,编译器也不会答应的。
可悲的是Android中几乎所有的API都是以整数集的方式来定义的,所以就要时刻提醒自己和组里的人,一定要传所定义的整数集中的常量。
那么我们能做的,除了要传整数集中定义的常量,对于那些以整数集方式定义的API,以外。更重要的是当自己定义接口的时候,尽量用Enum而不要使用整数集。
还有一点需要注意的是,对于某些弱类型语言,也就是说在编译时不会对类型做特别细致的检查,比如C++,C等,那么即使使用了Enum,也不一定安全,因为对于C++和C来讲Enum中的常量与整数常量完全一样,连编译器都分不清。所以,对于这类语言,只能寄希望于开发者了。
后记:
写完这篇,让我想起了另外一些与参数定义相关的问题,比如布尔型参数也不是一个很好的设计,因为使用者很难到底应该传True还是传False,特别是当方法名字不能体现Boolean参数作用时和文档不够清楚的时候。如果只有一个参数还好,根据方法名字和常识都能知道,比如:
代码如下:
Button.setEnabled(true); // enable the button
Button.setEnabled(false); // disable the button
但对于某些情况,当方法的名字不能体现Boolean参数的作用时,或是多于一个参数时,而方法的主要目的又不能体现Boolean参数的作用时,就很不清楚,比如:
代码如下:
// com/android/mms/data/ContactList.java
public String[] getNumbers(boolean);
您能猜出来这个boolean变量是决定是否要为彩信对联
系人做特殊的处理吗?您在使用这个API的时候能很快知道该传True还是该传False吗?当读到这些语句的时候:
代码如下:
String[] mms = getNumbers(true);
String[] sms = getNumbers(false);
您能知道True和False的含义与作用吗?至少我看到这样的代码时,如果不去跟踪它的实现,是猜不出来的。
但现实的问题是,API通常又需要从调用者那里得到做还是不做的决定。一个可行的途径是用方法来封装和隐藏,比如:
代码如下:
Button.setEnabled(true); // enable the button
Button.setEnabled(false); // disable the button
可以改成:
代码如下:
Button.enable();
Button.disable();
这是简单的情况,对于稍复杂的情况,比如后一个例子,可以添加另外的接口,而不是用重载方法,但内部的实现,可能还是需要重载,但是这就把问题缩小了,起码对使用者来说是隐藏的:
代码如下:
// com/android/mms/data/ContactList.java
public String[] getNumbersForSms();
public String[] getNumbersForMms();
这样一来,对外来讲就是良好的封装。内部实现可能还是需要一个类似这样的私有方法:
代码如下:
// com/android/mms/data/ContactList.java
public String[] getNumbersForSms() {
return getNumbers(false);
}
public String[] getNumbersForMms() {
return getNumbers(true);
}
private String[] getNumbers(boolean) {
// implementation
}
但至少把问题缩小化了,也可以加上注释来说明。就不必导致使用者来猜方法的用法和含义了。