28 กุมภาพันธ์ 2567
การแปลโปรเจ็กต์จากภาษาหนึ่งเป็นอีกภาษาหนึ่งไม่เพียงเกี่ยวกับการเปลี่ยนแปลงซอร์สโค้ดเท่านั้น แต่ยังเกี่ยวกับสภาพแวดล้อมที่เราดำเนินโปรเจ็กต์นั้นด้วย CodePorting.Translator Java Class Library ใช้สภาพแวดล้อมดังกล่าวผ่าน JCL (ไลบรารีคลาส Java) โดยคงตรรกะและโครงสร้างของไลบรารีคลาส .NET Framework ไว้ ซึ่งทำให้โปรเจ็กต์ที่แปลแล้วรู้สึกเหมือนอยู่บ้าน โดยซ่อนตัวจากการนำแพลตฟอร์ม Java ไปใช้
JCL (ไลบรารีคลาส Java) แตกต่างจากไลบรารีคลาส .NET ในการออกแบบทั่วไป การจัดการข้อยกเว้น และตรรกะ ดังนั้น หากเราตัดสินใจแปลโค้ดของเราจาก C# เป็น Java แค่เปลี่ยนชื่อคลาสและฟังก์ชันก็จะไม่ปลอดภัยแล้ว อาจมีวิธีแก้ไขในการสร้างโค้ดการห่อซึ่งจะสร้างตรรกะไลบรารีคลาส .NET Framework ขึ้นมาใหม่ แต่วิธีนี้จะทำให้โค้ด Java ที่ได้ออกมาจะแตกต่างอย่างมากจากโค้ด C# ต้นฉบับ ซึ่งไม่ใช่สิ่งที่เราคาดหวังไว้ – เราต้องการให้นักแปล คงโครงสร้างโปรแกรมดั้งเดิมไว้ ที่นี่เรากำลังมาถึงความจำเป็นในการใช้การแทนที่ Java ของไลบรารีคลาสเฟรมเวิร์ก .NET
เรามาเริ่มด้วยสิ่งที่ง่ายๆ:
using System;
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello, Example!");
}
}
เรามีคลาสจากไลบรารีคลาส .NET Framework – System.Console
โค้ด Java ที่แปลแล้วจะดูเป็นอย่างไร
import com.codeporting.ms.System.Console;
class Program
{
public static void main(String[] args)
{
Console.writeLine("Hello, Example!");
}
}
ดังที่คุณเห็น นักแปลจะแทนที่การอ้างอิงจากคลาส System.Console
ของ C# ไปเป็นคลาส Java com.codeporting.ms.System.Console
ซึ่งนำไปใช้ใน CodePorting.Translator Java Class Library
ทีนี้เรามาดูอีกตัวอย่างหนึ่ง:
using System;
using System.Collections.Generic;
class Program
{
public static void Main(string[] args)
{
PrintList(new List<string> { "Hello, list!", "I have a list for you to print!" });
}
public static void PrintList(List<string> list)
{
foreach(var item in list) Console.WriteLine(item);
}
}
โค้ด Java ที่แปลจะเป็นดังนี้:
import com.codeporting.ms.System.Collections.Generic.IGenericEnumerable;
import com.codeporting.ms.System.Collections.Generic.List;
import com.codeporting.ms.System.Console;
import com.codeporting.ms.System.IDisposable;
import java.util.Iterator;
class Program
{
public static void main(String[] args)
{
List<String> tmp = new List<String>();
tmp.addItem("Hello, list!");
tmp.addItem("I have a list for you to print!");
printList(tmp);
}
public static void printList(IGenericEnumerable<String> list)
{
//Foreach to while statement conversion
Iterator<String> variable1 = list.iterator();
try
{
while (variable1.hasNext())
{
String item = variable1.next();
Console.writeLine(item);
}
}
finally
{
if (variable1 != null)
{
((IDisposable)variable1).dispose();
}
}
}
}
ที่นี่เราเห็นข้อดีอีกอย่างหนึ่งจากการใช้ CodePorting.Translator Java Class Library – เรารักษาความสัมพันธ์ระหว่างนามธรรมของ C# System.Collections.Generic.List
ใช้อินเทอร์เฟซ IEnumerable
ซึ่งทำให้เราสามารถวนซ้ำผ่านอินเทอร์เฟซ foreach
Java มีอินเทอร์เฟซ java.lang.Iterable
และมันดูคล้ายกับ IEnumerable
แต่มีความแตกต่างเล็กน้อยในการออกแบบ ซึ่งอาจกลายเป็นการตัดสินใจสำหรับโปรเจ็กต์ขนาดใหญ่
แม้ว่าเราจะมีไลบรารีที่ดีให้ใช้ แต่โปรเจ็กต์ที่เราแปลจำเป็นต้องเข้าถึงและเข้าใจได้โดยลูกค้า และพวกเขาอาจต้องการใช้คลาส JCL คงจะดีถ้าซ่อนตัวจากโลกภายนอกที่เราใช้ CodePorting.Translator Java Class Library และที่นี่ เรามีฟีเจอร์ CodePorting.Translator ที่น่าสนใจอีกอย่างหนึ่ง: ApiChange คุณสมบัตินี้ทำอะไร? มันจะซ่อนวิธีการที่ใช้ CodePorting.Translator Java Class Library โดยสร้างวิธีการพร็อกซีที่ใช้คลาส JCL ให้เราดูตัวอย่าง:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Newspaper
{
public class Article
{
public DateTime Published { get; set; }
public string Content { get; set; }
}
public class Archive
{
List<Article> articles = new List<Article>();
public void AddArticle(Article article)
{
articles.Add(article);
}
public IEnumerable<Article> GetArticlesForPeriod(DateTime start, DateTime end)
{
if(start > end || start > DateTime.Now)
{
return new Article[0];
}
return articles.Where(article => article.Published >= start && article.Published <= end);
}
}
public class Program
{
public static void Main(string[] args)
{
var archive = new Archive();
archive.AddArticle(
new Article() {
Published = new DateTime(2012, 12, 20), Content = "End of the world comes tomorrow!" });
archive.AddArticle(
new Article() {
Published = new DateTime(2012, 12, 22), Content = "It was a huge joke..." });
var articles = archive.GetArticlesForPeriod(
new DateTime(2000, 1, 1),
new DateTime(2012, 12, 21));
foreach(var article in articles)
{
Console.WriteLine(article.Content);
}
}
}
}
คุณอาจเห็นคลาสง่ายๆ Archive
ที่นี่ซึ่งจัดเก็บบทความบางบทความและให้สิทธิ์เข้าถึงบทความเหล่านั้น โดยใช้ตัวกรองตามวันที่เผยแพร่บทความ
คลาส System.DateTime
เป็นส่วนหนึ่งของ ไลบรารีคลาส .NET Framework และแม้ว่าเราอาจใช้ในโครงการของเรา แต่เราต้องการที่จะซ่อนมันจากโลกภายนอก:
Article.java
package Newspaper;
import com.codeporting.ms.System.DateTime;
import java.util.Date;
public class Article
{
private DateTime auto_Published = new DateTime();
final DateTime getPublishedInternal() { return auto_Published.Clone(); }
public final Date getPublished() {
return DateTime.toJava(getPublishedInternal());
}
final void setPublishedInternal(DateTime value) { auto_Published = value.Clone(); }
public final void setPublished(Date value) {
setPublishedInternal(DateTime.fromJava(value));
}
private String auto_Content;
public final String getContent() { return auto_Content; }
public final void setContent(String value) { auto_Content = value; }
}
Archive.java
package Newspaper;
import com.codeporting.ms.System.Collections.Generic.IGenericEnumerable;
import com.codeporting.ms.System.Collections.Generic.List;
import com.codeporting.ms.System.DateTime;
import com.codeporting.ms.System.Func;
import java.util.Date;
public class Archive
{
private Archive[] Archive_this = {this};
private List<Article> articles = new List<Article>();
public final void addArticle(Article article)
{
articles.addItem(article);
}
final IGenericEnumerable<Article> getArticlesForPeriodInternal(DateTime start, DateTime end)
{
if(DateTime.op_GreaterThan(start, end) || DateTime.op_GreaterThan(start, DateTime.getNow()))
{
return com.codeporting.ms.System.Array.<Article>toGenericList(new Article[0]);
}
return articles.where(new Func<Article,Boolean>() {
public String getDelegateId() {
return System.identityHashCode(Archive_this[0]) + "-89480671";
}
public Boolean invoke(Newspaper.Article article) {
return DateTime.op_GreaterThanOrEqual(article.getPublishedInternal(), start)
&& DateTime.op_LessThanOrEqual(article.getPublishedInternal(), end);
}
});
}
public final java.lang.Iterable<Article> getArticlesForPeriod(Date start, Date end)
{
IGenericEnumerable<Article> temp=getArticlesForPeriodInternal(
DateTime.fromJava(start),
DateTime.fromJava(end));
java.util.ArrayList<Article> temp_java=new java.util.ArrayList<Article>();
{
com.codeporting.ms.System.Collections.Generic.IGenericEnumerator<Article> temp_iterator=temp.iterator();
while(temp_iterator.hasNext())
{
Article element=temp_iterator.next();
temp_java.add(element);
}
}
return temp_java;
}
}
Program.java
package Newspaper;
import com.codeporting.ms.System.Collections.Generic.IGenericEnumerable;
import com.codeporting.ms.System.Console;
import com.codeporting.ms.System.DateTime;
import com.codeporting.ms.System.IDisposable;
import java.util.Iterator;
public class Program
{
public static void main(String[] args)
{
Archive archive = new Archive();
Article tmp = new Article();
tmp.setPublishedInternal(new DateTime(2012, 12, 20));
tmp.setContent("End of the world comes tomorrow!" ) ;
archive.addArticle(tmp);
Article tmp_1 = new Article();
tmp_1.setPublishedInternal(new DateTime(2012, 12, 22));
tmp_1.setContent("It was a huge joke..." ) ;
archive.addArticle(tmp_1);
IGenericEnumerable<Article> articles = archive.getArticlesForPeriodInternal(
new DateTime(2000, 1, 1),
new DateTime(2012, 12, 21));
//Foreach to while statement conversion
Iterator<Article> variable1 = articles.iterator();
try
{
while (variable1.hasNext())
{
Article article = variable1.next();
Console.writeLine(article.getContent());
}
}
finally
{
if (variable1 != null)
{
((IDisposable)variable1).dispose();
}
}
}
}
โค้ดที่แปลเป็น Java ไม่มีการเข้าถึง CodePorting.Translator Java Class Library ผ่านทาง API สาธารณะ และโลก Java ภายนอกอาจโต้ตอบกับคลาส Archive
ของเรา โดยใช้วิธีพร็อกซีสาธารณะ
CodePorting.Translator Java Class Library มีเลเยอร์นามธรรมและการควบคุม JCL ซึ่งทำให้เราไม่ใส่ใจรายละเอียดการใช้งาน และช่วยให้เราคิดถึงปัญหาที่เราแก้ไขได้
นอกจากนี้ยังช่วยรักษาโครงสร้างของโค้ดต้นฉบับเพิ่มความเข้าใจและความโปร่งใสของผลการแปล