posted @
2010-01-10 10:47 square 閱讀(269) |
評論 (0) |
編輯 收藏
關(guān)鍵字:js驗證表單大全,用JS控制表單提交 ,javascript提交表單:
目錄:
1:js 字符串長度限制、判斷字符長度 、js限制輸入、限制不能輸入、textarea 長度限制
2.:js判斷漢字、判斷是否漢字 、只能輸入漢字
3:js判斷是否輸入英文、只能輸入英文
4:js只能輸入數(shù)字,判斷數(shù)字、驗證數(shù)字、檢測數(shù)字、判斷是否為數(shù)字、只能輸入數(shù)字
5:只能輸入英文字符和數(shù)字
6: js email驗證 、js 判斷email 、信箱/郵箱格式驗證
7:js字符過濾,屏蔽關(guān)鍵字
8:js密碼驗證、判斷密碼
2.1: js 不為空、為空或不是對象 、判斷為空 、判斷不為空
2.2:比較兩個表單項的值是否相同
2.3:表單只能為數(shù)字和"_",
2.4:表單項輸入數(shù)值/長度限定
2.5:中文/英文/數(shù)字/郵件地址合法性判斷
2.6:限定表單項不能輸入的字符
2.7表單的自符控制
2.8:form文本域的通用校驗函數(shù)
1. 長度限制
<script>
function test()
{
if(document.a.b.value.length>50)
{
alert("不能超過50個字符!");
document.a.b.focus();
return false;
}
}
</script>
<form. name=a nsubmit="return test()">
<textarea name="b" cols="40" wrap="VIRTUAL" rows="6"></textarea>
<input type="submit" name="Submit" value="check">
</form>
2. 只能是漢字
<input nkeyup="value="/oblog/value.replace(/[^\u4E00-\u9FA5]/g,'')">
3." 只能是英文
<script. language=javascript>
function onlyEng()
{
if(!(event.keyCode>=65&&event.keyCode<=90))
event.returnvalue=false;
}
</script>
<input nkeydown="onlyEng();">
4. 只能是數(shù)字
<script. language=javascript>
function onlyNum()
{
if(!((event.keyCode>=48&&event.keyCode<=57)||(event.keyCode>=96&&event.keyCode<=105)))
//考慮小鍵盤上的數(shù)字鍵
event.returnvalue=false;
}
</script>
<input nkeydown="onlyNum();">
5. 只能是英文字符和數(shù)字
6. 驗證油箱格式
<SCRIPT. LANGUAGE=javascript. RUNAT=Server>
function isEmail(strEmail) {
if (strEmail.search(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/) != -1)
return true;
else
alert("oh");
}
</SCRIPT>
<input type=text nblur=isEmail(this.value)>
7. 屏蔽關(guān)鍵字(這里屏蔽***和****)
<script. language="javascript1.2">
function test() {
if((a.b.value.indexOf ("***") == 0)||(a.b.value.indexOf ("****") == 0)){
alert(":)");
a.b.focus();
return false;}
}
</script>
<form. name=a nsubmit="return test()">
<input type=text name=b>
<input type="submit" name="Submit" value="check">
</form>
8. 兩次輸入密碼是否相同
<FORM. METHOD=POST ACTION="">
<input type="password" id="input1">
<input type="password" id="input2">
<input type="button" value="test" nclick="check()">
</FORM>
<script>
function check()
{
with(document.all){
if(input1.value!=input2.value)
{
alert("false")
input1.value = "";
input2.value = "";
}
else document.forms[0].submit();
}
}
</script>
夠了吧 :)
屏蔽右鍵 很酷
oncontextmenu="return false" ndragstart="return false" nselectstart="return false"
加在body中
二
2.1 表單項不能為空
<script language="javascript">
<!--
function CheckForm()
{
if (document.form.name.value.length == 0) {
alert("請輸入您姓名!");
document.form.name.focus();
return false;
}
return true;
}
-->
</script>
2.2 比較兩個表單項的值是否相同
<script language="javascript">
<!--
function CheckForm()
if (document.form.PWD.value != document.form.PWD_Again.value) {
alert("您兩次輸入的密碼不一樣!請重新輸入.");
document.ADDUser.PWD.focus();
return false;
}
return true;
}
-->
</script>
2.3 表單項只能為數(shù)字和"_",用于電話/銀行帳號驗證上,可擴展到域名注冊等
<script language="javascript">
<!--
function isNumber(String)
{
var Letters = "1234567890-"; //可以自己增加可輸入值
var i;
var c;
if(String.charAt( 0 )=='-')
return false;
if( String.charAt( String.length - 1 ) == '-' )
return false;
for( i = 0; i < String.length; i ++ )
{
c = String.charAt( i );
if (Letters.indexOf( c ) < 0)
return false;
}
return true;
}
function CheckForm()
{
if(! isNumber(document.form.TEL.value)) {
alert("您的電話號碼不合法!");
document.form.TEL.focus();
return false;
}
return true;
}
-->
</script>
2.4 表單項輸入數(shù)值/長度限定
<script language="javascript">
<!--
function CheckForm()
{
if (document.form.count.value > 100 || document.form.count.value < 1)
{
alert("輸入數(shù)值不能小于零大于100!");
document.form.count.focus();
return false;
}
if (document.form.MESSAGE.value.length<10)
{
alert("輸入文字小于10!");
document.form.MESSAGE.focus();
return false;
}
return true;
}
//-->
</script>
2.5 中文/英文/數(shù)字/郵件地址合法性判斷
<SCRIPT LANGUAGE="javascript">
<!--
function isEnglish(name) //英文值檢測
{
if(name.length == 0)
return false;
for(i = 0; i < name.length; i++) {
if(name.charCodeAt(i) > 128)
return false;
}
return true;
}
function isChinese(name) //中文值檢測
{
if(name.length == 0)
return false;
for(i = 0; i < name.length; i++) {
if(name.charCodeAt(i) > 128)
return true;
}
return false;
}
function isMail(name) // E-mail值檢測
{
if(! isEnglish(name))
return false;
i = name.indexOf(" at ");
j = name dot lastIndexOf(" at ");
if(i == -1)
return false;
if(i != j)
return false;
if(i == name dot length)
return false;
return true;
}
function isNumber(name) //數(shù)值檢測
{
if(name.length == 0)
return false;
for(i = 0; i < name.length; i++) {
if(name.charAt(i) < "0" || name.charAt(i) > "9")
return false;
}
return true;
}
function CheckForm()
{
if(! isMail(form.Email.value)) {
alert("您的電子郵件不合法!");
form.Email.focus();
return false;
}
if(! isEnglish(form.name.value)) {
alert("英文名不合法!");
form.name.focus();
return false;
}
if(! isChinese(form.cnname.value)) {
alert("中文名不合法!");
form.cnname.focus();
return false;
}
if(! isNumber(form.PublicZipCode.value)) {
alert("郵政編碼不合法!");
form.PublicZipCode.focus();
return false;
}
return true;
}
//-->
</SCRIPT>
2.6 限定表單項不能輸入的字符
<script language="javascript">
<!--
function contain(str,charset)// 字符串包含測試函數(shù)
{
var i;
for(i=0;i<charset.length;i++)
if(str.indexOf(charset.charAt(i))>=0)
return true;
return false;
}
function CheckForm()
{
if ((contain(document.form.NAME.value, "%\(\)><")) || (contain(document.form.MESSAGE.value, "%\(\)><")))
{
alert("輸入了非法字符");
document.form.NAME.focus();
return false;
}
return true;
}
//-->
</script>
1. 檢查一段字符串是否全由數(shù)字組成
---------------------------------------
<script. language="Javascript"><!--
function checkNum(str){return str.match(/\D/)==null}
alert(checkNum("1232142141"))
alert(checkNum("123214214a1"))
// --></script>
2. 怎么判斷是否是字符
---------------------------------------
if (/[^\x00-\xff]/g.test(s)) alert("含有漢字");
else alert("全是字符");
3. 怎么判斷是否含有漢字
---------------------------------------
if (escape(str).indexOf("%u")!=-1) alert("含有漢字");
else alert("全是字符");
4. 郵箱格式驗證
---------------------------------------
//函數(shù)名:chkemail
//功能介紹:檢查是否為Email Address
//參數(shù)說明:要檢查的字符串
//返回值:0:不是 1:是
function chkemail(a)
{ var i=a.length;
var temp = a.indexOf('@');
var tempd = a.indexOf('.');
if (temp > 1) {
if ((i-temp) > 3){
if ((i-tempd)>0){
return 1;
}
}
}
return 0;
}
5. 數(shù)字格式驗證
---------------------------------------
//函數(shù)名:fucCheckNUM
//功能介紹:檢查是否為數(shù)字
//參數(shù)說明:要檢查的數(shù)字
//返回值:1為是數(shù)字,0為不是數(shù)字
function fucCheckNUM(NUM)
{
var i,j,strTemp;
strTemp="0123456789";
if ( NUM.length== 0)
return 0
for (i=0;i<NUM.length;i++)
{
j=strTemp.indexOf(NUM.charAt(i));
if (j==-1)
{
//說明有字符不是數(shù)字
return 0;
}
}
//說明是數(shù)字
return 1;
}
6. 電話號碼格式驗證
---------------------------------------
//函數(shù)名:fucCheckTEL
//功能介紹:檢查是否為電話號碼
//參數(shù)說明:要檢查的字符串
//返回值:1為是合法,0為不合法
function fucCheckTEL(TEL)
{
var i,j,strTemp;
strTemp="0123456789-()# ";
for (i=0;i<TEL.length;i++)
{
j=strTemp.indexOf(TEL.charAt(i));
if (j==-1)
{
//說明有字符不合法
return 0;
}
}
//說明合法
return 1;
}
7. 判斷輸入是否為中文的函數(shù)
---------------------------------------
function ischinese(s){
var ret=true;
for(var i=0;i<s.length;i++)
ret=ret && (s.charCodeAt(i)>=10000);
return ret;
}
8. 綜合的判斷用戶輸入的合法性的函數(shù)
---------------------------------------
<script. language="javascript">
//限制輸入字符的位數(shù)開始
//m是用戶輸入,n是要限制的位數(shù)
function issmall(m,n)
{
if ((m<n) && (m>0))
{
return(false);
}
else
{return(true);}
}
9. 判斷密碼是否輸入一致
---------------------------------------
function issame(str1,str2)
{
if (str1==str2)
{return(true);}
else
{return(false);}
}
10. 判斷用戶名是否為數(shù)字字母下滑線
---------------------------------------
function notchinese(str){
var reg=/[^A-Za-z0-9_]/g
if (reg.test(str)){
return (false);
}else{
return(true); }
}
2.8. form文本域的通用校驗函數(shù)
---------------------------------------
作用:檢測所有必須非空的input文本,比如姓名,賬號,郵件地址等等。
該校驗現(xiàn)在只針對文本域,如果要針對form里面的其他域?qū)ο?,可以改變判斷條件。
使用方法:在要檢測的文本域中加入title文字。文字是在提示信息,你要提示給用戶的該字段的中文名。比如要檢測用戶名
html如下
,當然,最好用可視化工具比如dreamweaver什么的來編輯域。
如果要檢測數(shù)字類型數(shù)據(jù)的話,再把域的id統(tǒng)一為sz.
javascript判斷日期類型比較麻煩,所以就沒有做日期類型校驗的程序了.高手可以補充。
程序比較草,只是提供一個思路。拋磚引玉! :)
哦,對了,函數(shù)調(diào)用方法:< form nsubmit="return dovalidate()">
function dovalidate()
{
fm=document.forms[0] //只檢測一個form,如果是多個可以改變判斷條件
for(i=0;i<fm.length;i++)
{
//檢測判斷條件,根據(jù)類型不同可以修改
if(fm[i].tagName.toUpperCase()=="INPUT" &&fm[i].type.toUpperCase()=="TEXT" && (fm[i].title!=""))
if(fm[i].value="/blog/="")//
{
str_warn1=fm[i].title+"不能為空!";
alert(str_warn1);
fm[i].focus();
return false;
}
if(fm[i].id.toUpperCase()=="SZ")//數(shù)字校驗
{
if(isNaN(fm[i].value))
{ str_warn2=fm[i].title+"格式不對";
alert(str_warn2);
fm[i].focus();
return false;
}
}
}
return true;
}
posted @
2008-08-30 21:27 square 閱讀(1435) |
評論 (0) |
編輯 收藏
20060627UMLChinaIntrotoUML.part1.rar
20060627UMLChinaIntrotoUML.part2.rar
20060627UMLChinaIntrotoUML.part3.rar
20060627UMLChinaIntrotoUML.part4.rar
20060627UMLChinaIntrotoUML.part5.rar
posted @
2007-11-25 17:18 square 閱讀(306) |
評論 (0) |
編輯 收藏
以下是網(wǎng)友王垠寫的關(guān)于學習Linux的忠告。但只要稍加替換,它完全可以用來解決FF與IE,五筆與拼音,QQ與MSN,IBM與HP,甚至是SONY與任天堂粉絲之間的種種爭端。
1. 不要當“傳教士”
很多人在討論區(qū)不斷的引起 "Linux vs. Windows" 之類的討論,甚至爭的面紅耳赤,這是沒有必要的。 這種爭論是浪費時間而沒有任何用處的。對,你花了一下午,用許多事實“捍衛(wèi)”了 “Linux 比 Windows 好” 這個說法。但是 Windows 的支持者并不會喜歡上 Linux,他們只是稍微退縮一下,然后找一些新的證據(jù)來跟你辯論。 世界上的人們都在利用Linux 研究最前沿的科學,我們還在這里討論 “要不要用Linux” 這種無聊的問題,什么時候才能趕上時代前進的步伐? 什么叫做“Windows 支持者”,什么叫做“Linux 支持者”?我們?yōu)槭裁匆С帜骋粋€而反對另外一個?你不需要為 Linux “護法”,不需要成為“Linux 支持者”或者“GNU傳教士”,GNU/Linux 已經(jīng)用事實向世界證明了它們的威力,已經(jīng)被大多數(shù)人接受。你只需要安安靜靜享受 GNU/Linux 給你的樂趣和自由。 你需要關(guān)心的不是你的工具是什么,而是你用它做了什么。精通 Linux 并不說明任何問題,因為它只是一個工具而已。如果你用 Windows 能很好的完成你的任務(wù),那你就沒有必要費時間去熟悉 Linux。直到有一天你發(fā)現(xiàn)一項任務(wù)只有 Linux 才能完成的時候再換也不遲,因為你身邊的 Linux 的愛好者一定會很樂意的幫助你。
工具不是人,不應(yīng)該對工具有感情。這是你在進行任何對工具的討論前需要提醒自己的事情。面對一些容易引起爭論的東西:Word 和 TeX;Emacs 和 VIM;MAXIMA,Mathematica 和 Maple;Gnome, FVWM 和 KDE;Mutt 和 Pine …… 一定要冷靜的對自己說:“我不站在它們?nèi)魏我贿?,因為它們不是人?#8221; 各人的需要不同,生活的環(huán)境不同。對你來說好的東西,對別人來說不一定好,我們需要尊重別人的選擇。如果你當面說別人正在用的程序不好,沒有人會樂意接受你的意見。我從來沒有建議過我爸爸不用 Windows + WPS,而用 Linux + LaTeX 來處理他的英語試卷。因為 WPS 是我爸爸的選擇,他能用 WPS 編輯出很好的試題去測試他的學生,那就足夠了。
我曾經(jīng)幫我爸爸做了一個 perl 程序,能夠自動從一種我自己設(shè)計的 markup 語言轉(zhuǎn)化成 LaTeX 格式的英語試卷??梢宰詣訉υ囶}編號,亂序排版選擇題的選項,自動生成答案表,生成老師用的顯示答案的版本,自動對短文改錯題進行優(yōu)化分段,自動拼寫檢查,圖形化的配置方式…… 我爸爸高興的用了一段時間,可是后來他想用 WPS 里的一種標題樣式,而我不在家,無法為他修改程序。所以他又換回了 WPS。這就像有人送愛因斯坦一罐剃須泡沫一樣,剛開始幾天,發(fā)現(xiàn)他神采飛揚,不斷夸這個東西真舒服。過了幾天,發(fā)現(xiàn)愛因斯坦又開始用白水剃胡子了,因為剃須泡沫用完了,他懶得自己去買那個東西。這只是習慣問題。
2. 不要強迫自己
喜歡電腦的人總是有某些心理強迫傾向。有的人說:“鍵盤比鼠標快。我不要用鼠標。這樣才有高效率。” 所以他在編輯器里無論什么時候總是用 20w, 10j 這樣的命令到達目的點。他甚至覺得圖形界面是多余的,干脆 Xwindow 都不裝。 全部用鍵盤看起來的確比讓手離開鍵盤去拿鼠標,再回來“快” 多了,但是快的擊鍵頻率不等于工作的高效率,對你的健康更沒有什么好處。這只能把你變成打鍵盤的機器。 當你正在檢查你的文章或者程序,思維正在隨著字符的含義流動,突然 20w, 10j 這樣的東西出現(xiàn)在你的腦子里,是不是會打斷思路?不?那說明你當時思考的問題比較簡單,這些干擾還不會起到副作用。
其實很多人用電腦的時候,思想都受到某種教條的束縛,上面這個只是眾多教條中的一種。某些人制造了很多這種教條,用他的工作方式來要求別人,嘲笑方式跟他不一樣的人。比如有的人嘲笑其它人寫 C 程序不按 8 字符縮進,嘲笑別人在 vi 里用方向鍵,嘲笑別人不知道 PVM 是什么,嘲笑其它人用 JAVA, C# 這種由 GC 回收內(nèi)存語言…… 你不用管各種各樣的教條,電腦只是你的奴隸,你想怎么用就怎么用。沒有人能夠約束你,沒有人可以嘲笑你的工作方式。電腦明天就不再是這個樣子,所以今天你不用完全了解它。你沒有必要知道別人創(chuàng)造的一切,因為你需要留點時間自己創(chuàng)造些東西。Just have fun! 當你下次修改文章的時候,不妨試試悠閑的用鼠標在你眼睛看到的地方輕輕點一下。
3. 不要“玩 Linux”
很多人用 Linux 的時候會感覺很迷茫,該用哪個發(fā)行呢?是不是我少裝了什么?怎么升級這么快啊!怎么這么不穩(wěn)定!每當遇到新的軟件他就想試用,每當新的版本出現(xiàn),他就更新,然后用鼠標在新的菜單里選擇從來沒見過的程序來用用。 其實你是為了Linux而使用Linux,而沒有找到正確的理由來利用 Linux。你首先要明確用電腦的目的,你用它是為了解決你的實際問題,而不是為了學習安裝操作系統(tǒng),不是為了測試哪個版本好用,不是為了“趕上潮流”,更不是因為你硬盤太大了,你想多占點空間。 如果你啟動了電腦之后不知道應(yīng)該干什么,那么最好先不要用電腦,因為你可能有更重要的事情需要做。
4. 不用挑剔發(fā)行版本
很多人剛開始用 Linux 的時候,總是在懷疑別的發(fā)行版本是否比自己正在用的這個好,總是懷疑自己以后時候會失去支持,不得不換用別的發(fā)行。所以很多人今天是 Redhat,明天又換成了 debian, 一會兒又是 gentoo, …… 甚至有的人在一臺機器上裝了兩個版本的 Linux,然后比較哪一個好。 其實你完全沒有必要這樣做,任何發(fā)行,只要你熟悉了,你在上面的工作方式幾乎是不會受到任何影響的。
我以前一直用的 Redhat,當我有一天在我的一臺新機器上安裝 debian 時,我發(fā)現(xiàn)使用 Redhat 的經(jīng)驗完全沒有浪費。我用了一個下午就配置好了 debian,使它服服貼貼的聽我的話,就跟沒有換發(fā)行一樣。 Debian, TurboLinux, SuSE, Redhat, Gentoo, ... 任何一個版本都是不錯的。很多人認為自己攢一個 LFS 是高水平黑客的象征,但是不是每個人都有精力去了解所有細節(jié)。 如果你是用于個人的日常事物和科研,可以試試 debian。它是我見過的最方便的一個發(fā)行。
5. 不要盲目升級
不知道這是心理作用還是什么,有的人看到比較大的版本號,就會很想換成那個。很多人的 Redhat 本來配置的很舒服了,可是一旦 Redhat 發(fā)行新的版本,他們就會盡快下載過來,然后選擇升級安裝。結(jié)果很多時候把自己原來修改得很好的配置文件給沖掉了。新的軟件又帶來了新的問題,比如有一次我的 rxvt 升級到 2.7.8 就跟 miniChinput 沖突了,升級到 Redhat 8.0,發(fā)現(xiàn) xmms 居然缺省不能放mp3了,XFree86 的 xtt 模塊在 I810 上有新的 bug,會導(dǎo)致 Mozilla 突然退出。 如果你已經(jīng)配置好了一切,千萬別再整體升級了,這會浪費你很多很多時間的,不值得。有句話說得好:"If it's not broken, don't fix it." 如果你的程序能夠完成你需要做的事情,你何必升級呢?
6. 不要配置你不需要的東西
如果你只想做一個像我這樣的普通用戶,主要目的是用 Linux 來完成自己的科研任務(wù)和日常工作,那就可以不用系統(tǒng)管理員或者網(wǎng)絡(luò)管理員的標準來要求自己,因為當一個系統(tǒng)和網(wǎng)絡(luò)管理員確實很辛苦。普通用戶學習那些不經(jīng)常用到的復(fù)雜的維護系統(tǒng)的工具,其實是浪費時間,學了不用是會很快忘記的! 我不是一個合格的網(wǎng)絡(luò)管理員,我的服務(wù)器都只設(shè)置了我自己需要的功能,設(shè)置好 ssh, ftp 已經(jīng)足夠了,那樣可以省去我很多麻煩。我從來不過度考慮“安全”,因為 Linux 缺省已經(jīng)很安全了。我沒有磁帶機,就不用管 tar 的那些稀奇古怪的參數(shù)了,czf, xzf, ztf 已經(jīng)可以滿足我所有的需要。sed, awk, ... 我也只會幾種常用的命令行。
7. 不要習慣的使用 root 帳號。
在需要的時候才 su! 這是很多剛接觸 UNIX 類操作系統(tǒng)的人常見的現(xiàn)象,他們不喜歡在管理系統(tǒng)的時候才 su, 而是一直用 root 帳號干所有事情,配置系統(tǒng),安裝程序,瀏覽網(wǎng)頁,玩游戲,編程 …… 結(jié)果有一天,他不小心在某個系統(tǒng)目錄使用了 rm * ... 后果不堪設(shè)想……
8. 不要用商業(yè)的眼光來看 Linux。
Linux 不是商業(yè)軟件,所以不要用要求 Solaris, Windows 那樣的眼光來看 Linux. 自由軟件的作者們從來不拉攏用戶,他們對用戶不負有任何責任。實際上在自由軟件的世界里,“開發(fā)者”和“用戶” 并沒有明確的界限,大家是朋友。 自由軟件很可能只是滿足作者和他的朋友的需要,甚至是為了好玩而創(chuàng)造的。自由軟件不是完美的,自由軟件承認自己有缺點,它不會自吹自擂,蒙蔽“用戶”的耳目。這種對作者責任的解脫激發(fā)了作者的創(chuàng)造力,他們不用過分考慮“向上兼容”,他們往往比背上重重包袱的商業(yè)軟件結(jié)構(gòu)更合理,技術(shù)更先進。 所以當你用某個自由軟件遇到困難的時候,不應(yīng)該埋怨軟件的作者,因為他們對你并沒有義務(wù)。
你不應(yīng)該把自己當成一個挑剔的顧客,而要把自己作為這個軟件的顧問和一個和藹的建議者,這樣你才能理解作者寫這個程序時的快樂,在遇到問題時向作者反映,幫助他完善這個軟件,成為一個快樂的參與者。就像你的哥哥送你一個他用舊了的自行車,你應(yīng)該珍惜這份友情,而不要在車壞了,或者騎車摔了一交的時候大罵你的哥哥。如果你真的不能使用這種合作的心態(tài),那么最好不要使用這個軟件。 這是一種先進的文化,它包含了互相合作,科學創(chuàng)新的精神。理解這一點不是很容易,很多人往往是因為不能理解這種文化而離開自由軟件。這對于作者來說并沒有什么損失。
9. 干你的正事去
很多人跟我說,你的網(wǎng)頁浪費我好多時間來配置這配置那,一會兒是 FVWM,一會兒是 Mutt …… 嗯……那些東西都是我有空的時候一點一點積累的,如果你想一次性搞定所有那些東西,恐怕得花你幾個星期甚至幾個月的時間!并不是一定要搞定所有這些東西你才能正常工作的。除非你真的非得利用某個程序,或者你閑著沒事,否則你可以不管這些東西。
10. 上面幾條僅供參考 以上只是個人意見,不一定適合所有人。取舍由你了!
posted @
2007-11-25 17:09 square 閱讀(326) |
評論 (0) |
編輯 收藏
摘要: 基礎(chǔ)知識:
1.C++或Java中的異常處理機制的簡單原理和應(yīng)用。
當JAVA程序違反了JAVA的語義規(guī)則時,JAVA虛擬機就會將發(fā)生的錯誤表示為一個異常。違反語義規(guī)則包括2種情況。一種是JAVA類庫內(nèi)置的語義檢查。例如數(shù)組下標越界,會引發(fā)IndexOutOfBoundsException;訪問null的對象時會引發(fā)NullPointerException。另一種情況就是JAVA允許程序員...
閱讀全文
posted @
2006-07-17 22:06 square 閱讀(701) |
評論 (0) |
編輯 收藏
abstract class和interface是Java語言中對于抽象類定義進行支持的兩種機制,正是由于這兩種機制的存在,才賦予了Java強大的面向?qū)ο竽芰?。abstract class和interface之間在對于抽象類定義的支持方面具有很大的相似性,甚至可以相互替換,因此很多開發(fā)者在進行抽象類定義時對于abstract class和interface的選擇顯得比較隨意。其實,兩者之間還是有很大的區(qū)別的,對于它們的選擇甚至反映出對于問題領(lǐng)域本質(zhì)的理解、對于設(shè)計意圖的理解是否正確、合理。本文將對它們之間的區(qū)別進行一番剖析,試圖給開發(fā)者提供一個在二者之間進行選擇的依據(jù)。
理解抽象類abstract class和interface在Java語言中都是用來進行抽象類(本文中的抽象類并非從abstract class翻譯而來,它表示的是一個抽象體,而abstract class為Java語言中用于定義抽象類的一種方法,請讀者注意區(qū)分)定義的,那么什么是抽象類,使用抽象類能為我們帶來什么好處呢?
在面向?qū)ο蟮母拍钪?,我們知道所有的對象都是通過類來描繪的,但是反過來卻不是這樣。并不是所有的類都是用來描繪對象的,如果一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。抽象類往往用來表征我們在對問題領(lǐng)域進行分析、設(shè)計中得出的抽象概念,是對一系列看上去不同,但是本質(zhì)上相同的具體概念的抽象。比如:如果我們進行一個圖形編輯軟件的開發(fā),就會發(fā)現(xiàn)問題領(lǐng)域存在著圓、三角形這樣一些具體概念,它們是不同的,但是它們又都屬于形狀這樣一個概念,形狀這個概念在問題領(lǐng)域是不存在的,它就是一個抽象概念。正是因為抽象的概念在問題領(lǐng)域沒有對應(yīng)的具體概念,所以用以表征抽象概念的抽象類是不能夠?qū)嵗摹?br />
在面向?qū)ο箢I(lǐng)域,抽象類主要用來進行類型隱藏。我們可以構(gòu)造出一個固定的一組行為的抽象描述,但是這組行為卻能夠有任意個可能的具體實現(xiàn)方式。這個抽象描述就是抽象類,而這一組任意個可能的具體實現(xiàn)則表現(xiàn)為所有可能的派生類。模塊可以操作一個抽象體。由于模塊依賴于一個固定的抽象體,因此它可以是不允許修改的;同時,通過從這個抽象體派生,也可擴展此模塊的行為功能。熟悉OCP的讀者一定知道,為了能夠?qū)崿F(xiàn)面向?qū)ο笤O(shè)計的一個最核心的原則OCP(Open-Closed Principle),抽象類是其中的關(guān)鍵所在。
從語法定義層面看abstract class和interface在語法層面,Java語言對于abstract class和interface給出了不同的定義方式,下面以定義一個名為Demo的抽象類為例來說明這種不同。
使用abstract class的方式定義Demo抽象類的方式如下:
abstract class Demo {
????????abstract void method1();
????????abstract void method2();
????????…
}
使用interface的方式定義Demo抽象類的方式如下:
interface Demo {
????????void method1();
????????void method2();
????????…
}
在abstract class方式中,Demo可以有自己的數(shù)據(jù)成員,也可以有非abstarct的成員方法,而在interface方式的實現(xiàn)中,Demo只能夠有靜態(tài)的不能被修改的數(shù)據(jù)成員(也就是必須是static final的,不過在interface中一般不定義數(shù)據(jù)成員),所有的成員方法都是abstract的。從某種意義上說,interface是一種特殊形式的abstract class。
對于abstract class和interface在語法定義層面更多的細節(jié)問題,不是本文的重點,不再贅述,讀者可以參閱參考文獻〔1〕獲得更多的相關(guān)內(nèi)容。
從編程層面看abstract class和interface從編程的角度來看,abstract class和interface都可以用來實現(xiàn)"design by contract"的思想。但是在具體的使用上面還是有一些區(qū)別的。
首先,abstract class在Java語言中表示的是一種繼承關(guān)系,一個類只能使用一次繼承關(guān)系。但是,一個類卻可以實現(xiàn)多個interface。也許,這是Java語言的設(shè)計者在考慮Java對于多重繼承的支持方面的一種折中考慮吧。
其次,在abstract class的定義中,我們可以賦予方法的默認行為。但是在interface的定義中,方法卻不能擁有默認行為,為了繞過這個限制,必須使用委托,但是這會 增加一些復(fù)雜性,有時會造成很大的麻煩。
在抽象類中不能定義默認行為還存在另一個比較嚴重的問題,那就是可能會造成維護上的麻煩。因為如果后來想修改類的界面(一般通過abstract class或者interface來表示)以適應(yīng)新的情況(比如,添加新的方法或者給已用的方法中添加新的參數(shù))時,就會非常的麻煩,可能要花費很多的時間(對于派生類很多的情況,尤為如此)。但是如果界面是通過abstract class來實現(xiàn)的,那么可能就只需要修改定義在abstract class中的默認行為就可以了。
同樣,如果不能在抽象類中定義默認行為,就會導(dǎo)致同樣的方法實現(xiàn)出現(xiàn)在該抽象類的每一個派生類中,違反了"one rule,one place"原則,造成代碼重復(fù),同樣不利于以后的維護。因此,在abstract class和interface間進行選擇時要非常的小心。
從設(shè)計理念層面看abstract class和interface上面主要從語法定義和編程的角度論述了abstract class和interface的區(qū)別,這些層面的區(qū)別是比較低層次的、非本質(zhì)的。本小節(jié)將從另一個層面:abstract class和interface所反映出的設(shè)計理念,來分析一下二者的區(qū)別。作者認為,從這個層面進行分析才能理解二者概念的本質(zhì)所在。
前面已經(jīng)提到過,abstarct class在Java語言中體現(xiàn)了一種繼承關(guān)系,要想使得繼承關(guān)系合理,父類和派生類之間必須存在"is a"關(guān)系,即父類和派生類在概念本質(zhì)上應(yīng)該是相同的(參考文獻〔3〕中有關(guān)于"is a"關(guān)系的大篇幅深入的論述,有興趣的讀者可以參考)。對于interface 來說則不然,并不要求interface的實現(xiàn)者和interface定義在概念本質(zhì)上是一致的,僅僅是實現(xiàn)了interface定義的契約而已。為了使論述便于理解,下面將通過一個簡單的實例進行說明。
考慮這樣一個例子,假設(shè)在我們的問題領(lǐng)域中有一個關(guān)于Door的抽象概念,該Door具有執(zhí)行兩個動作open和close,此時我們可以通過abstract class或者interface來定義一個表示該抽象概念的類型,定義方式分別如下所示:
使用abstract class方式定義Door:
abstract class Door {
????????abstract void open();
????????abstract void close();
}
使用interface方式定義Door:
interface Door {
????????void open();
????????void close();
}
其他具體的Door類型可以extends使用abstract class方式定義的Door或者implements使用interface方式定義的Door??雌饋砗孟袷褂胊bstract class和interface沒有大的區(qū)別。
如果現(xiàn)在要求Door還要具有報警的功能。我們該如何設(shè)計針對該例子的類結(jié)構(gòu)呢(在本例中,主要是為了展示abstract class和interface反映在設(shè)計理念上的區(qū)別,其他方面無關(guān)的問題都做了簡化或者忽略)?下面將羅列出可能的解決方案,并從設(shè)計理念層面對這些不同的方案進行分析。
解決方案一:
簡單的在Door的定義中增加一個alarm方法,如下:
abstract class Door {
????????abstract void open();
????????abstract void close();
????????abstract void alarm();
}
或者
interface Door {
????????void open();
????????void close();
????????void alarm();
}
那么具有報警功能的AlarmDoor的定義方式如下:
class AlarmDoor extends Door {
????????void open() { … }
????????void close() { … }
????????void alarm() { … }
}
或者
class AlarmDoor implements Door {
????????void open() { … }
????????void close() { … }
????????void alarm() { … }
}
這種方法違反了面向?qū)ο笤O(shè)計中的一個核心原則ISP(Interface Segregation Priciple),在Door的定義中把Door概念本身固有的行為方法和另外一個概念"報警器"的行為方法混在了一起。這樣引起的一個問題是那些僅僅依賴于Door這個概念的模塊會因為"報警器"這個概念的改變(比如:修改alarm方法的參數(shù))而改變,反之依然。
解決方案二:
既然open、close和alarm屬于兩個不同的概念,根據(jù)ISP原則應(yīng)該把它們分別定義在代表這兩個概念的抽象類中。定義方式有:這兩個概念都使用abstract class方式定義;兩個概念都使用interface方式定義;一個概念使用abstract class方式定義,另一個概念使用interface方式定義。
顯然,由于Java語言不支持多重繼承,所以兩個概念都使用abstract class方式定義是不可行的。后面兩種方式都是可行的,但是對于它們的選擇卻反映出對于問題領(lǐng)域中的概念本質(zhì)的理解、對于設(shè)計意圖的反映是否正確、合理。我們一一來分析、說明。
如果兩個概念都使用interface方式來定義,那么就反映出兩個問題:1、我們可能沒有理解清楚問題領(lǐng)域,AlarmDoor在概念本質(zhì)上到底是Door還是報警器?2、如果我們對于問題領(lǐng)域的理解沒有問題,比如:我們通過對于問題領(lǐng)域的分析發(fā)現(xiàn)AlarmDoor在概念本質(zhì)上和Door是一致的,那么我們在實現(xiàn)時就沒有能夠正確的揭示我們的設(shè)計意圖,因為在這兩個概念的定義上(均使用interface方式定義)反映不出上述含義。
如果我們對于問題領(lǐng)域的理解是:AlarmDoor在概念本質(zhì)上是Door,同時它有具有報警的功能。我們該如何來設(shè)計、實現(xiàn)來明確的反映出我們的意思呢?前面已經(jīng)說過,abstract class在Java語言中表示一種繼承關(guān)系,而繼承關(guān)系在本質(zhì)上是"is a"關(guān)系。所以對于Door這個概念,我們應(yīng)該使用abstarct class方式來定義。另外,AlarmDoor又具有報警功能,說明它又能夠完成報警概念中定義的行為,所以報警概念可以通過interface方式定義。如下所示:
abstract class Door {
????????abstract void open();
????????abstract void close();
}
interface Alarm {
????????void alarm();
}
class AlarmDoor extends Door implements Alarm {
????????void open() { … }
????????void close() { … }
?? ????????void alarm() { … }
}
這種實現(xiàn)方式基本上能夠明確的反映出我們對于問題領(lǐng)域的理解,正確的揭示我們的設(shè)計意圖。其實abstract class表示的是"is a"關(guān)系,interface表示的是"like a"關(guān)系,大家在選擇時可以作為一個依據(jù),當然這是建立在對問題領(lǐng)域的理解上的,比如:如果我們認為AlarmDoor在概念本質(zhì)上是報警器,同時又具有Door的功能,那么上述的定義方式就要反過來了。
結(jié)論abstract class和interface是Java語言中的兩種定義抽象類的方式,它們之間有很大的相似性。但是對于它們的選擇卻又往往反映出對于問題領(lǐng)域中的概念本質(zhì)的理解、對于設(shè)計意圖的反映是否正確、合理,因為它們表現(xiàn)了概念間的不同的關(guān)系(雖然都能夠?qū)崿F(xiàn)需求的功能)。這其實也是語言的一種的慣用法,希望讀者朋友能夠細細體會。
posted @
2006-07-15 20:59 square 閱讀(389) |
評論 (0) |
編輯 收藏