1. 程式人生 > >Java編程也要從娃娃抓起

Java編程也要從娃娃抓起

區別 oss sse 淡出 fin 應該 類和對象 () 這就是

因為市面上沒有教孩子編程的教程書,於是本文作者自己編了一本。InfoQ的用戶朋友們有沒有教自己孩子編程的呢?我司倒是有一個教自家跳小蘋果的孩子學C語言的。

十二年前,我的小兒子Dave出現在我的辦公室,手裏拿著Java教程。Dave讓我教他編程,這樣他就能自己寫遊戲了。

那時候我已經寫了幾本關於Java的書,還同時教幾門計算機編程課,但那都是面向成人的;Amazon上沒有任何適合用來教孩子編程的書。在Google上搜索了幾個小時,我能找到的一些為孩子準備的編程教程也只是淺嘗輒止,或者是最基礎的那種類似於“聰明兔(譯者註:即reader rabbit,美國著名幼兒教育品牌)”的書。所以我決定自己寫一本書。

那時我的大兒子Yuri在大學裏主修動漫,他答應為我的書畫插圖。當我完成草稿的時候,沒有出版商願意出版它,原因有兩個:

少兒編程書根本沒有市場。
我希望這本書能彩印,較之於黑白印刷,這大大增加了成本。
沒什麽大不了的。我在網上發布了此書的pdf版本供大家免費下載。一年後,幾位好心的法國家長把它譯成了法語,然後一些來自東歐的Java愛好者又把它譯成了俄語和烏克蘭語。這些版本仍然可以從網上免費下載到。

今年早些時候,我收到了一封意外的電子郵件,來自於No Starch出版社——問我是否有興趣寫一本給孩子看的Java編程書籍?我又問了一次,“你們願意彩印嗎?”,出乎我意料的是,他們馬上同意了,並且給我看了很多他們出版的教孩子編程的書籍,是其他語種的。時代變了……長話短說,我接受了。一年很快要過去了,這本書將會在2015年春季付印。

用Java來教孩子編程好嗎?

為了回答這個問題,我們首先要定義“孩子”這個詞。對於12歲以下的孩子來說,我相信Java作為第一門編程語言有點太復雜了。低齡一點的孩子一開始最好用一些寫好的程序模塊來搭建可視化程序。MIT創建了Scratch,對於8歲大的孩子來說,它是一個很好的激發編程興趣的工具。10歲的小孩就可以更進一步,通過Greenfoot開始學習真正地使用Java來編程。

但是我認為,任何12歲以上的孩子,只要對編程有興趣,就可以一本正經地去學習Java編程了,並且可以使用專業的工具來學。在之前為孩子寫的那本書裏,我使用Eclipse作為IDE,但在現在這本新書裏,我選擇了IntelliJ IDEA社區版,它也是免費的。

教成人和教小孩Java的區別在於,孩子們對於編寫GUI程序的反響更熱烈,而Java也很擅長做這個。我說的是JavaFX;Swing框架已經過時了,想用Swing來寫出點像樣的程序,需要很專業的知識。

JavaFX則提供了豐富的工具,並且非常優雅地隔離了界面和應用邏輯。JavaFX自帶了“Scene Builder”,一個可視化的GUI設計工具,它可以生成用FXML描述的GUI;FXML是一種基於XML的語言,可以通過聲明的方式來創建GUI。不過不用擔心,孩子們不需要自己去寫FXML——他們只需要把UI控件拖拽到畫布(canvas)上,Scene Builder就會生成FXML。

少兒Java教育家

如果說12年前的孩子對編程還不是那麽感興趣的話,那麽今天的很多孩子已經很喜歡編程了。時代變了,於是,世界各地都有編程愛好者在花時間和精力給孩子介紹編程。我們要向Stephan Janssen致敬,他創立了Devoxx4Kids運動,用一種創造性的方式來教孩子編程。

這種運動最早開始於比利時,但如今很多國家都加入了。在美國,舊金山分會的領導人是Arun Gupta,而Matt Raible運營著丹佛分會。如果有位於曼哈頓的公司願意提供場地給孩子們搞活動的話,我已經準備好貢獻我的時間,在紐約建立一個分支機構。

我要為Stephen Chin獻上掌聲,他來自Oracle,他經常背著一個袋子滿世界走,那個袋子裏裝滿了可編程設備。今年早些時候,我參加了他的演講“瑪麗有個小小的lambda表達式”(譯者註:英文名“Mary Had a Little Lambda”,此名字借用了著名的英語兒歌“Mary Had a Little Lamb”,lamb和lambda詞形相近),在演講中他通過演示復雜的遊戲解釋了Java。

今年夏天,我參加了在希臘舉行的JCrete“非會議”(譯者註:unconference,一種顛覆傳統式會議的新形式,會議內容由參與者自己制定,主張開放式討論)。其他與會者都帶著筆記本電腦來,Stephen卻帶來了兩打硬件開發套件,他舉行了一個研討會,在會上孩子們用Java編了一個機器人,可以跳Sirtaki舞(譯者註:希臘民間舞蹈)。

我肯定世界各地還有其他的好心人在給孩子們普及Java。已經誕生20年之久的Java語言正在越變越年輕。

本書節選

感謝有這樣的機會能給InfoQ的讀者呈現我將要出版的書籍“Java for Kids”中的兩段節選。在本書中我使用了IntelliJ IDEA社區版,JetBrains出品的免費又好用的IDE。第一段節選是關於類和對象的簡單介紹。第二段來自於Tic-Tac-Toe(譯者註:一種棋類遊戲)章節。教孩子的時候,程序的可視化程度越高越好。這就是為什麽我要在總共12章中的5章都使用了JavaFX。讀者們需要編寫一個計算器和兩個遊戲:Tic-Tac-Toe和Ping-Pong。

本書節選1:類和對象

在現實世界中你會看到和用到各種對象,每個對象都屬於某個“種類”,比如玩具、食物、動物、電子產品等等。在Java中我們不說一種對象,而說一類對象。類就像是一個對象的藍圖。你將要編寫的所有程序都是由各種類組成的。

Java定義了各種數據類型。有些很簡單,像int,代表整數。有些復雜一點,它們就是類。比如System類,它可以用於在屏幕上打印文字、退出程序或清理計算機的內存。

你安裝了Java後,數千個Java類被下載到你的計算機中。你的Java程序中包含的類也可能代表來自真實世界的對象。如果說類是一種數據類型,那麽對象就代表了一種特殊的類型。舉個例子,你看到街上有十只狗,他們都代表了Dog這個類。

程序員在開始寫程序之前,先要決定需要使用哪些類,每個類要創建多少對象。比如,在遊戲應用中他們可以定義Player類,並以此創建兩個對象。

當程序員互相交流的時候,他們可能會說“對Player類做某些操作”或者“用Player對象做某些操作”。我們需要分辨類和對象這兩個詞的不同含義。

我們來看看Java類是如何組成的。最基礎的類可能什麽都不包含。看看下面的類聲明:

class VideoGame {}

這是個空的類——它不帶有任何信息,也幹不了任何事,因為兩個大括號之間沒有任何代碼。從Java語法的角度看,這個類是合法的,計算機不會報錯——class是一個有效的關鍵字,緊接著是名字VideoGame,大括號要成對出現。但如果我們的程序想幹點什麽,我們需要定義有實際意義的類。所以我們需要給類加裝方法和屬性:

方法定義了一個類所能做的操作。
屬性描述了一個類的各種性質。
我們來給VideoGame類填上內容。這個類可以有一些方法,告訴我們這個類的對象能做什麽:開始遊戲、停止遊戲、保存分數、要求上Facebook點贊等等。這個類也可以有一些屬性(也叫域):顏色、價格和其他。代表VideoGame類的一個對象看起來是這樣的:

class VideoGame {
String color;
int price;
void start () {
// 開始遊戲的代碼放在這裏
}
void stop () {
// 停止遊戲的代碼放在這裏
}
void saveScore(String playerName, int score) {
// 保存分數的代碼放在這裏
}
}**

這個類有兩個屬性color和price。color屬性是String類型的,這種類型用於保存文本。price是int型的,用於保存整數。VideoGame類有三個方法:start、stop和saveScore。這些都是我們的視頻遊戲能采取的動作。目前,這些方法只有以雙斜杠//開頭的一行字。

如果一行文字以雙斜杠開頭,那它就是單行的註釋——只是對代碼段的描述。如果你需要寫多行的註釋,只要輸入一個斜杠和一個星號/,然後輸入任意行的文字,最後以一個星號和一個斜杠結尾/,代表註釋結束。

我們不會去創造一個真正的視頻遊戲,因為我們才開始學編程。但到本書的後面部分,我們會開發Tic-Tac-Toe和Ping-Pong遊戲。

但是難道你不覺得所有遊戲都有共同點嗎?每個遊戲都需要有一種方法來開始和停止或保存分數。當你以面向對象的方式編寫一個程序,你要開始思考如何使類擁有的屬性和方法保持絕對的最少。然後你可以基於第一個類來添加更多特殊的功能——在本章節後面部分你會學到繼承。這就是為什麽VideoGame類只擁有視頻遊戲所共有的屬性和方法。

技術分享圖片

圖1:視頻遊戲的對象

類還是對象

在本節中我將向你展示如何基於類來創建對象實例,並向你介紹繼承的概念。

為了復用你或者其他人已經寫好的代碼,你可以基於一個類創建另一個,它會繼承前一個類的所有屬性和方法。繼承別的類創建的類稱為“子類”,被繼承的類稱為“父類”。下面的代碼展示了繼承VideoGame類的新類PlayStation4。

class PlayStation4 extends VideoGame{```

String hardDiskSize;
// 其他屬性和方法可以在這裏聲明
// 方法shareOnFacebooks檢查用戶是否已經登錄了
// 如果沒有,它會顯示一個窗口,帶有以下信息
// “在分享你的分數之前請先登錄Facebook”
void shareOnFacebook(){
// 在Facebook上分享的代碼在這裏
System.out.println("Hey, Facebook, I got PlayStation4 with " + hardDiskSize);
}
void shareOnTwitter(){
// 在Twitter上分享的代碼在這裏
System.out.println("Hey, Twitter, I got PlayStation4 with " + hardDiskSize);
}
}

語句extends VideoGame表示PlayStation4類是VideoGame類的子類。我們也可以說PlayStation4類繼承了VideoGame類或者說“擴展”了VideoGame類,這也意味著子類(PlayStation4)既可以使用父類(VideoGame)中定義的屬性,也可以使用父類(VideoGame)中定義的所有方法(並擴展它們),我在書的後面部分會解釋。

註意PlayStation4類即使沒有定義屬性price和color,以及方法start、stop和savaScore,但這個類的對象還是可以使用所有這些屬性和方法。它們是從VideoGame類繼承過來的,這些代碼不需要拷貝/粘貼到PlayStation4類中。

當我們創建一個對象的實例時,我們真正所做的是基於某個類的聲明,在計算機內存中創建了一個對象。舉個例子,下面的CreatePlayStation4Objects程序使用new運算符創建了兩個PlayStation4類的實例。

它聲明了兩個PlayStation4型的變量,分別是firstPlayStation和secondPlayStation,每個都指向了內存中的一個獨立對象。註意這些對象的屬性hardDiskSize有不同的值(500GB和1TB)。這個程序對第一個對象調用了shareOnFacebook方法,而對第二個對象調用了shareOnTwitter。

public class CreatePlayStation4Objects {
public static void main(String[] args) {
// 創建一個PlayStation4類的實例
PlayStation4 firstPlayStation = new PlayStation4();
firstPlayStation.hardDiskSize = "500GB";
// 對第一個實例調用shareOnFacebook方法
firstPlayStation.shareOnFacebook();
// 創建另一個PlayStation4類的實例
PlayStation4 secondPlayStation = new PlayStation4();
secondPlayStation.hardDiskSize = "1TB";
// 對第二個實例調用shareOnFacebook方法
secondPlayStation.shareOnTwitter();
}

運行CreatePlayStation4Objects會打印以下內容:

Hey, Facebook, I got PlayStation4 with 500GB
Hey, Twitter, I got PlayStation4 with 1TB

如果一個遊戲公司要生產10000個這樣的遊戲,那麽程序員可以說他們創建了10000個PlayStation4的實例。遊戲公司和一個真正的遊戲的關系就類似於Java類和它在內存中的實例的關系。在現實世界中遊戲公司制作一個真正的遊戲,和Java編程世界中創建PlayStation4對象實例類似。只是每個實例會有些不一樣,比如本例中的內部磁盤大小。

技術分享圖片

圖2:一個類,兩個實例

一般情況下,程序先創建Java類的對象實例,才能使用它的屬性和方法。遊戲公司也一樣——他們使用同一份原本生產出數千份遊戲拷貝。即使這些拷貝代表了同一個類,它們還是可能有不一樣的屬性——有些是黑的色,另一些則是銀色的。有些有500GB硬盤,有些則有1TB。

本書節選2:改變樣式和使用效果

這是第十章的節選,讀到那裏讀者已經掌握了JavaFX的基礎,寫過一個登錄窗口和一個計算器,並且知道如何在界面上應用CSS樣式。Tic-Tac-Toe遊戲的基本功能也已經實現,但是如果能使制勝的三顆棋子一目了然就更好了(譯者註:Tic-Tac-Toe以三子在一直線上為勝)。

加亮制勝棋子

制勝棋子的樣式應該可以動態改變(在運行的時候)。首先,我們需要給CSS文件添加一個樣式來顯示制勝的X-O棋子。然後Controller類可以對棋子調用setStyle方法,決定制勝的棋子使用哪種樣式。

我想改變制勝棋子的背景,但是這次我不想用單色了,我想用漸變色。在計算機圖形中,漸變色是指用混合的顏色去填充一個區域,並且相鄰顏色之間是平滑過渡。顏色漸變分線性的和放射狀的,這篇維基百科的文章有這兩者的例子。

我們的遊戲中使用放射狀漸變。我們可以使用兩種或更多的顏色來組成漸變色。我們給制勝棋子使用三種顏色吧。棋子的背景色會從白色轉變到淡×××,再到草綠色。棋子上的文字標簽,我們使用紅色。

要動態改變GUI組件的樣式,你可以調用setStyle,並指定顏色作為參數,舉個例子:

myButton.setStyle("-fx-text-fill: red;");

但是,在你的Java程序中寫死CSS規則不是一個好主意。如果你想改變樣式該怎麽辦(比如把顏色從紅色改成粉色)?你不想搜遍所有的Java文件來找出所有使用這個樣式的地方。而且,改變嵌在代碼中的樣式,會導致程序必須重新編譯,誰會為了一個簡單的修改這麽幹!所以把樣式定義放在外部的CSS文件中會比較好,改起來就比較靈活。

至此,我們已經使用了CSS類型選擇器來改變指定組件的樣式。但是,CSS允許你定義一個樣式並給它取名,這樣,就不僅僅是特定的組件類型可以用它,各種組件都可以通過指定名字來使用它。在CSS中,這種樣式叫做類選擇器(class selectors)。我們來給tictactoe.css添加一個叫做.winning-square的類選擇器。

.winning-square {
-fx-text-fill: red;
-fx-background-color: radial-gradient( radius 100%, white, lightyellow, lawngreen);
}

這裏的樣式選擇器.winning-square包括了兩條樣式規則:一條是要把按鈕的顏色設為紅色,另一條是要把按鈕的背景色設為我們的放射狀漸變色。我們的Java程序必須得到按鈕現有樣式的引用,然後再添加一個.winning-square,這就會覆蓋按鈕原來的文字和背景顏色。方法highlightWinningCombo看起來是這樣的:

private void highlightWinningCombo(Button first, Button second, Button third){
first.getStyleClass().add("winning-square");
second.getStyleClass().add("winning-square");
third.getStyleClass().add("winning-square");
}

在給Controller類添加完find3InARow和highlightWinningCombo方法後,試著玩玩這個遊戲。制勝的棋子看起來就是下面這個樣子:
技術分享圖片

圖3:我們贏了!

JavaFX包括了多種視覺效果和變換動畫,這些可以使你的界面變得更有意思。

要使用這些效果和動畫,你需要在javafx.scene.effect和javafx.animation包中進行相應的選擇。我會給你演示一下如何在我們的制勝棋子上使用淡出的變換效果。每個制勝棋子不停地淡出,然後又回復到初始狀態。我們要給Controller類添加一個applyFadeTransition方法。

private void applyFadeTransition(Button winningButton) {
FadeTransition ft = new FadeTransition(Duration.millis(1000), winningButton);
ft.setFromValue(1.0);
ft.setToValue(0.1);
ft.setCycleCount(10);
ft.setAutoReverse(true);
ft.play();
}

這段代碼創建了一個動畫類FadeTransition的實例,這個動畫會持續1000毫秒(等於1秒),然後把這個動畫分配給制勝棋子。然後它又設置了淡出的參數,把棋子的透明度從1改到了0.1(0.0意味著完全透明)。

把樣式數量設為10代表動畫會播放10次。因為調用了setAutoReverse(true),這個動畫會在第一個周期中正向播放,在第二個周期中反向播放,如此循環往復。play方法則啟動了動畫。給highlightWinningCombo添加以下三行代碼,這個動畫就會在winningButton組件上播放。

applyFadeTransition(first);
applyFadeTransition(second);
applyFadeTransition(third);
下面的截屏告訴你動畫播放結束後的樣子。
技術分享圖片

圖4:淡出的制勝棋子

把這張圖和前面一張比一比。或者運行書中的代碼,看看動畫是什麽樣子的,就更好了。

喜歡小編輕輕點個關註哦!

Java編程也要從娃娃抓起