Friday, October 10, 2014

நிரலாக்க மொழிகளும் அவற்றின் பிரதிபலிப்பும். (Programming Languages and Reflection)

இன்றைய காலத்தில் உருவாக்கப்படும் பெருன்பான்மையான உயர் நிலை நிரலாக்க மொழிகள் பிரதிபலிப்பு பயன்பாட்டு நிரலாக்க இடைமுகம் (ப.நி.இ) ஒன்றையும் கொண்டுள்ளன. 

மூன்றாம் நபர் ஒருவர், மென்பொருள் சட்டகம் ஒன்றை அமைக்கும் பொது இந்த ப.நி.இ கள் பெரும் துணைபுரிகின்றன. அதுமட்டும் அல்லாது, எங்களின் நிரலாக்கமும், எதிர்காலத்தில் ஆரம்ப நிரலாக்க கோப்புகளில் மாற்றங்களை செய்யாது, அதிக அல்லது வித்தியாசமான இயல்புகளுடன் விரிவுபடுத்த கூடியதாகவும், அல்லது இயக்கநிலையில் அவற்றின் இயங்கும் தன்மையை மாற்றி அமைக்க கூடியதாக அமைத்து கொள்ளுவதற்கும் இது பெரிதும் உதவும்.

நாம் நிரலாக்கம் ஒன்றை எழுதும் போது, இப்படி ஒரு ப.நி.இ எங்களின் நிரலாக்க மொழியில் உண்டா? என்பதையும், அதன் பயன்பாடு மற்றும் வரையறைகள் என்ன என்பதையும் அறிந்து, முயன்ற அளவு அவற்றை பயன்படுத்தினோமானால், அழகான, விரிவு படுத்தகூடிய நிரலாக்கங்களை எழுதிக்கொள்ளலாம்.

Tomcat போன்ற வலை வழங்கன் , Spring போன்ற மென்பொருள் சட்டகம் அல்லது Android போன்ற இன்றைய இயக்க தளங்கள் வரை இவை பெருமளவில் பயன்படுகின்றன.

மென்பொருள் சட்டகங்கள் என்பவை, சில குறிப்பிட்ட ஒத்த இயல்புகளை வழங்க கூடிய மென்பொருட்களை வடிவமைக்க தேவையான பொதுவான இயல்புகளுகளை உள்ளடக்கி வடிவமைக்கப்படும்.  பின்பு, மென்பொருள பொறியியலாளர்கள்  தங்கள் தேவைக்கேற்ப கூடுதல்  நிரலாக்கங்களை சேர்த்து விரிவுபடுத்தவோ அல்லது இறுதிப் பயன்பாடு கொண்ட மென்பொருட்களை உருவாக்கிக்கொள்ளவோ பயன்படுத்துவார்கள்.

இவ்வாறன சட்டகங்களை  அமைத்துக்கொள்ளும் போது, அவ் நிரலாக்கங்களால் இயக்கபோகும் எமது நிரலாக்கங்கள் கொண்டிருக்கும் வகுப்புகள்  அல்லது அவற்றின் பண்புகளோ செயலிகளோ தெரிந்திருக்க வாய்ப்பில்லை. அனால் அவற்றின் பெயர்களை வழங்குவதன் மூலம் புதிதாக சேர்க்கப்பட்ட நிரலாக்கங்களை இயக்க கூடியதாக இருக்க வேண்டும்.

இதனை ஒரு உதாரணத்துடன் பார்ப்பது இலகுவாக இருக்கும். ஜாவா நிரலாக்க மொழி இத்தகையான ப.நி.இ கொண்டுள்ளது. எனவே ஜாவா மொழியை கொண்டு சிறிய உதாரணத்தைப் பார்ப்போம்.

கீழ்காணும் வகுப்புகளை பார்ப்போம்.

இந்த வகுப்பு ஒரு வரியை திரையில் எழுதக்கூடியது.

public class MyPrinter {
public void print(){
System.out.println("My printer printing");
}
}

இந்த வகுப்பு ஆரம்பத்திலும் முடிலும் கோடுகளை வரைகின்றது. அத்துடன் இயக்க ஆரம்ப செயலியை கொண்டுள்ளது .

public class Starter {
public static void main(String[] args) {
MyPrinter printer = new MyPrinter();
System.out.println("==================================");
printer.print();
System.out.println("==================================");
}
}

வகுப்பு இயங்கியதும், திரையில் கிழ்கண்டவாறு இருக்கும்.

> java Starter  
==================================
My printer printing
==================================

இப்போது கீழ்காணும் புதிய வகுப்பு ஒன்றை சேர்ப்போம்.

public class YourPrinter {
public void print(){
System.out.println("Your printer printing");
}
}

இதனை மேலே எழுதிய Starter வகுப்பின் உதவியுடன் இயங்க செய்வோம்.

இதற்க்கு, Starter வகுப்பின்
MyPrinter printer = new MyPrinter(); 
வார்த்தைக்கு பதிலாக,
YourPrinter printer = new YourPrinter();
வார்த்தையை மாற்றவேண்டும்.

இப்போது உங்களுக்கு புரிந்திருக்கும். Starter வகுப்பு MyPrinter, YourPrinter வகுப்புகளை இயங்க பயன்படுத்த முடியும். ஆனால் Starter வகுப்பினுள் அதற்கேற்ற மாற்றங்கள் செய்யவேண்டி உள்ளது.

Starter வகுப்பில் மாற்றம் செய்யாது இரண்டு வகுப்புகையும் மாறி மாறி இயக்க என்ன செய்ய வேண்டும் என்று பார்ப்போம்.

முதலில் Printer என்னும் இடைமுகம் ஒன்றை அறிமுகம் செய்வோம்.

public interface Printer {
void print();
}

MyPrinter, YourPrinter  வகுப்புகளை இவ் இடைமுகத்தில் இருந்து மரபியல்பு பெறச்செய்வோம்.

public class MyPrinter implements Printer{
...
}

public class YourPrinter implements Printer{
...
}

Starter  வகுப்பினை இவ்வாறு மாற்றுவோம்.

public class Starter {
public static void main(String[] args) {
Printer printer = null;
if(args[0].equals("MyPrinter")){
printer = new YourPrinter();
}
if(args[0].equals("YourPrinter")){
printer = new YourPrinter();
}
System.out.println("==================================");
printer.print();
System.out.println("==================================");
}
}

இனி Starter  வகுப்பில் எந்தமாற்றமும் செய்யாது MyPrinter, YourPrinter வகுப்புகளை கீழ்க்கண்டவாறு இயக்கலாம்.

>java Starter MyPrinter
==================================
My printer printing
==================================

>java Starter YourPrinter
==================================
Your printer printing
==================================

இங்குபார்த்தால் Starter  வகுப்பு MyPrinter, YourPrinter வகுப்புகளுடன் சேர்ந்து விதம்விதமான இயல்புகளை எமக்கு தருகின்றது. எனவே இந்த Starter  வகுப்பை ஒரு சட்டகமாக பிறருக்கு வழங்கலாம். ஆனால் இந்நிலையில் அவ்வாறு செய்ய முடியாது.

ஏன் இந்நிலையில் Starter வகுப்பு ஒரு சட்டகம் இல்லை என்று பார்ப்போம்?

இப்போது வேறு ஒருவர் TheirPrinter வகுப்பு ஒன்றை உருவாக்குகின்றார்.

public class TheirPrinter implements Printer {
public void print() {
System.out.println("Their printer printing");
}
}

இதனை Starter உடன் இயங்க செய்ய கீழ் காணும் வார்த்தைகளை Starter வாகுப்புடன் சேர்க்க வேண்டும்.

if(args[0].equals("TheirPrinter")){
printer = new TheirPrinter();
}

சட்டகம் அமைக்கும் போது இது சாத்தியமற்றது. ஏன்னெனில் எதிர்காலத்தில் உருவாக்கப்படும் வகுப்புகளை எமது நிரலாக்கத்தில்  பயன்படுத்த முடியாது.

ஆகவே Starter வகுப்பை ஒரு சட்டகமாக மாற்ற வேண்டுமெனில், இயக்கநிலையில் வகுப்பின் பெயரைக்கொண்டு ஒருபொருளை உருவாக்கிக்கொள்ள கூடியதாக இருக்க வேண்டும். அவ் வகுப்பு Printer இடைமுகத்தின் மரபியலை கொண்டிருந்தால், Printer வகை இனம்காட்டி கொண்டு print செயலியை இயக்கலாம் .

இவ்விடத்தில்தான் எமக்கு பிரதிபலிப்பு ப.நி.இ உதவிசெய்கின்றன.

Starter வகுப்பின்

if(args[0].equals("...")){
printer = ...
}

வார்த்தைகளுக்கு பதிலாக, கீழ்காணும் வார்த்தைகளை மாற்றலாம்.

// வகுப்பை தேடுகிறது 
Class<?> forName = Class.forName(args[0]); 
// வகுப்பில் இருந்து பொருளை உருவாக்குகிறது 
Printer printer = (Printer) forName.newInstance(); 

இதன் பின்னர், Starter வகுப்பில் எந்த மாற்றமும் செய்யாது, MyPrinterYourPrinter மட்டுமல்லாது TheirPrinter போன்ற புதிதாக உருவாக்கப்படும் வகுப்புகளையும் பாவித்து கொள்ளலாம்.இவ்வகையில் பிரதிபலிப்பு ப.நி.இ விரிவுபடுத்த கூடிய நிரலாக்கம் ஒன்றை உருவாக்க எமக்கு உதவி உள்ளது .

இதுவரை விபரித்தவை, பிரதிபலிப்பு ப.நி.இ  பற்றிய ஒரு நல்ல அறிமுகத்தை தந்திருக்கும் என்று நினைக்கிறன். பிரதிபலிப்பு ப.நி.இ பற்றி கூடுதலாக அடுத்த அடுத்த பாகங்களில் எழுதுகிறேன்.