หลังจากที่ไม่ค่อยเรียนรู้อะไรใหม่ ๆ เกี่ยวกับ Java ช่วงนี้ก็ไปเจอะกับอะไรที่น่าสนใจเข้าครับ เป็นภาษาเขียนโปรแกรมที่ชื่อว่า Xtend ซึ่งเป็นโครงการหนึ่งจากมูลนิธิ Eclipse นั่นเอง
นิยามของ Xtend ก็คือ Modernized Java ก็คือการจับเอาภาษา Java ที่อายุกว่า 10 ปีมาแต่งหน้าทำผมเสียใหม่ให้ดูทันสมัย ทัดเทียมกับภาษาเกิดใหม่รุ่นหลาน แต่ยังไม่ทิ้งกลิ่นเดิม ๆ ของ Java
จุดเด่นของ Xtend นั้นก็คือ ตัวโค๊ดที่เขียนด้วย Xtend จะถูกคอมไพล์ไปเป็นโค๊ดในภาษา Java ก่อนที่จะถูกคอมไพล์อีกรอบด้วย Java Compiler ดังนั้นจึงรับประกันได้ว่าโปรแกรมที่เขียนจะเข้ากันได้กับ library หรือโปรแกรมอื่น ๆ ที่เขียนด้วย Java ได้แน่นอน 100 %
ตามธรรมเนียมแล้ว โปรแกรมแรกที่เขียนก็ต้องเป็น Hello World ก่อน Hello World ในภาษา Xtend นั้นมีหน้าตาแบบนี้ครับ
class HelloWorld {
def static void main(String[] args) {
println("Hello World")
}
}
สำหรับชาวชวาอย่างเรา ๆ มันดูคุ้น ๆ ใช่มั้ยครับ โค๊ดข้างบนจะถูกแปลเป็นโค๊ดในภาษา Java ก่อน ซึ่งผลลัพท์มันก็จะเป็นแบบนี้
import org.eclipse.xtext.xbase.lib.InputOutput;
public class HelloWorld {
public static void main(final String[] args) {
InputOutput.println("Hello World");
}
}
ก็แทบจะแม๊พมาตรง ๆ เลย เห็นแล้วก็ อ้าว ไม่เห็นหน้าตื่นเต้นตรงไหนเลยนี่นา ?
ลองเทียบความแตกต่างระหว่างโค๊ดของผม ที่เขียนด้วย Java กับที่เขียนด้วย Xtend ดูนะครับ
package com.playground_soft.chord;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.View;
import android.widget.ListView;
import com.playground_soft.chord.db.DatabaseHelper;
import com.playground_soft.chord.type.Song;
import com.playground_soft.chord.widget.SongListAdapter;
public class _SongListFragment extends ListFragment implements
RefreshThread.OnFinishHandler {
private DatabaseHelper mDbHelper;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onDestroy() {
super.onDestroy();
mDbHelper.close();
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Intent intent = new Intent(getActivity(),
SongDisplayActivity.class);
Song song = (Song)getListAdapter().getItem(position);
intent.setData(Uri.fromFile(song.getFile()));
intent.putExtra("iternal", true);
this.startActivity(intent);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Intent intent = this.getActivity().getIntent();
String artist = intent.getStringExtra("artist");
mDbHelper = new DatabaseHelper(this.getActivity());
this.updateSongList(artist);
}
public void updateSongList(String artist) {
Song mSongs[] = mDbHelper.querySong(artist, true, null, true);
SongListAdapter adapter = new SongListAdapter(getActivity(),
mSongs);
setListAdapter(adapter);
}
@Override
public void onFinished() {
updateSongList(null);
}
}
เทียบกับ เวอร์ชั่น Xtend
package com.playground_soft.chord
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.support.v4.app.ListFragment
import android.view.View
import android.widget.ListView
import com.playground_soft.chord.db.DatabaseHelper
import com.playground_soft.chord.type.Song
import com.playground_soft.chord.widget.SongListAdapter
public class SongListFragment extends ListFragment implements RefreshThread$OnFinishHandler {
DatabaseHelper mDbHelper
override onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
hasOptionsMenu = true
}
override void onDestroy() {
super.onDestroy
mDbHelper.close
}
override onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id)
val song = listAdapter.getItem(position) as Song
val intent = new Intent(activity, typeof(SongDisplayActivity))
intent => [
data = Uri::fromFile(song.file)
putExtra("iternal", true)
]
startActivity(intent)
}
override onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState)
val artist = activity.intent.getStringExtra("artist")
updateSongList(artist)
}
def updateSongList(String artist) {
if (mDbHelper == null)
mDbHelper = new DatabaseHelper(activity)
val mSongs = mDbHelper.querySong(artist, true, null, true)
val adapter = new SongListAdapter(activity, mSongs)
setListAdapter(adapter)
}
override onFinished() {
updateSongList(null)
}
}
จะเห็นว่า โค๊ดดูสะอาดกว่า อ่านง่ายกว่า แต่มีบางจุดที่อาจจะดูงง ๆ ต้องศึกษาสักพักถึงจะเริ่มชินครับ ผมว่าที่จะดูงงที่สุดก็คงเป็นฟีเจอร์ของ Xtend ที่เรียกว่า property
สำหรับ property ใน Xtend นั้นจะต่างกับ C# ตรงที่มันเป็น implicit ก็คือ ถ้ามีการเขียนเมธอด getX() ขึ้นมาในคลาส เราสามารถเรียกใช้เมธอดนี้ในรูปของตัวแปร x ได้เลย แต่จะอ่านได้อย๋างเดียว แต่ถ้ามีเมธอด setX() ที่รับพารามิเตอร์ตัวเดียว จะสามารถเขียนได้ด้วย
วิธีการประกาศตัวแปร ใน java ต้องระบุ type แต่ใน Xtend จะใช้คีย์เวิร์ด var แทน แล้ว type ของตัวแปรนั้นจะถูกกำหนดด้วยค่าที่ใส่เข้าไปในตอนแรก เช่น var index = 0 นั้น ตัวแปรชื่อ index จะมี type เป็น int อะไรทำนองนี้
พูดแค่นี้ก่อนท่าจะดีกว่า … สำหรับใครที่สนใจอยากอ่านก่อนก็เข้าไปศึกษาได้ที่ http://www.eclipse.org/xtend/index.html ครับ
ปล. สังเกตดี ๆ โค๊ดข้างล่างไม่มี semi-colon เลย ในภาษา Xtend semi-colon ปิดท้ายบรรทัดนั้น จะใส่ก็ได้ หรือไม่ใส่ก็ได้ครับ
โปรแกรมเมอร์ C++ และผู้นิยมดนตรี