آموزش زبان برنامه نویسی Groovy – جلسه دوم (Syntax)
زبان برنامه نویسی groovy یک زبان برنامه نویسی شی گرا هست که روی ماشین مجازی جاوا به عنوان مفسر ویا کامپایل اجرا می شود. ما در این مقاله در ادامه آموزش زبان برنامه نویسی groovy تهیه شده توسط آی تی پورت به معرفی رشته ها در این زبان پرداخته ایم. در جلسه اول آموزش Groovy به مباحث زیر پرداختیم.
- کامنت
- کلمات کلیدی
- شناسه ها
در جلسه دوم آموزش این زبان به بحث رشته ها و نحوه پیاده سازی آن می پردازیم.
در این بخش از آموزش زبان برنامه نویسی groovy ما به معرفی انواع رشته ها می پردازیم. حروف الفبا به صورت زنجیره ای از کاراکترها به نام رشته نشان داده می شوند. زبان برنامه نویسی groovy به شما امکان می دهد اشیا java.lang.String و همچنین GStrings (groovy.lang.GString) را که در دیگر زبان های برنامه نویسی رشته های interpolated نیز نامیده می شوند، نمونه برداری کنید.
رشته Single-quoted
در این قسمت از آموزش زبان برنامه نویسی groovy به رشته های Single-quoted می پردازیم. رشته های Single-quoted مجموعه ای از کارکتر ها هستند که با ‘ محصور شده اند:
'a single-quoted string'
java.lang.String بیانگر رشته های ساده هستند. و از interpolation پشتیبانی نمی کنند.
اتصال رشته
تمام رشته های Groovy را می توان با عملگر + پیوند داد:
assert 'ab' == 'a'+'b'
رشته Triple-single-quoted
امام در ادامه آموزش زبان برنامه نویسی groovy ، رشته های Triple-single-quoted مجموعه ای از کاراکتر ها هستند که توسط ”’ احاطه شده اند:
'''a triple-single-quoted string'''
java.lang.String بیانگر رشته های سه گانه تک نقل شده ساده هستند. و از interpolation پشتیبانی نمی کنند.
Triple-single-quoted ممکن است چندین خط را دربر بگیرد. محتوای رشته می تواند مرزهای خط را عبور دهد بدون اینکه نیازی به تقسیم رشته در چند قطعه و بدون علائم اتصال باشد:
def aMultilineString = '''line one line two line three'''
اگر کد شما دارای تو رفتگی باشد، در متن یک کلاس، رشته شما حاوی فضای خالی تورفتگی خواهد بود. کیت توسعه Groovy شامل روش هایی برای از بین بردن فرورفتگی با روش ()String # stripIndent و با روش ()String # stripMargin است. که برای مشخص کردن متن از ابتدای رشته، یک کاراکتر جداکننده می گیرد.
هنگام ایجاد یک رشته به شرح زیر:
def startingAndEndingWithANewline = ''' line one line two line three '''
مشاهده خواهید کرد که رشته حاصل دارای یک خط جدید به عنوان کاراکتر اول است. با وارد کردن کاراکتر \ می توان نوشته ها را به خطوط بعدی منتقل کنیم:
def strippedFirstNewline = '''\ line one line two line three ''' assert !strippedFirstNewline.startsWith('\n')
کاراکتر های شکست
برای جلوگیری از خاتمه دادن به رشته، می توانید از نقل قول های تک با کاراکتر \ استفاده کنید:
'an escaped single quote: \' needs a backslash'
و شما می توانید با یک عکس العمل مضاعف از کاراکتر Escape کنید:
'an escaped escape character: \\ needs a double backslash'
برخی از کاراکترهای خاص نیز از \ به عنوان کاراکتر Escape استفاده می کنند:
در مورد انواع دیگر رشته ها که بعداً بحث خواهند شد.
توالی Unicode escape
در این قسمت از آموزش زبان برنامه نویسی groovy ، برای کاراکتر هایی که در صفحه کلید شما وجود ندارند، می توانید از توالی های Unicode escape استفاده کنید: یک \، به دنبال “u” و سپس ۴ رقم هگزادسیمال.
به عنوان مثال، نماد واحد پول یورو را می توان با موارد زیر نشان داد:
'The Euro currency symbol: \u20AC'
رشته Double-quoted
قسمت بعدی آموزش زبان برنامه نویسی groovy ، رشته های Double-quoted مجموعه ای از کاراکتر ها هستند که با ” احاطه شده اند:
"a double-quoted string"
java.lang.String رشته های Double-quoted ساده هستند. اگر عبارتی الحاقی وجود نداشته باشد رشته ای هستند.
groovy.lang.GString در صورت وجود interpolation نمونه هایی از آن را بر می گرداند.
برای اجتناب از یک نقل قول مضاعف، می توانید از کاراکتر backslash استفاده کنید. مانند:
“یک نقل قول مضاعف: \” “.
رشته interpolation
در قسمت های قبلی آموزش زبان برنامه نویسی groovy یاد گرفتیم هر عبارت Groovy، یک interpolation است که هنگام ارزیابی رشته، جایگزین مقدار آن می شود. عبارات نگهدارنده مکان با {}$ احاطه شده اند. آکولادها ممکن است برای عبارات نقطه ای بدون ابهام حذف شوند، یعنی در این موارد فقط می توانیم از یک پیشوند $ استفاده کنیم. GString به روشی که یک String منتقل می شود، مقدار عبارت درون متغیر نگهدارنده به نمایش رشته آن ارزیابی می شود (با فراخوانی ()toString روی آن عبارت) و رشته حاصل به متد منتقل می شود.
در اینجا، ما یک رشته داریم که یک متغیر نگهدارنده به یک متغیر محلی ارجاع می دهد:
def name = 'Guillaume' // a plain string def greeting = "Hello ${name}" assert greeting.toString() == 'Hello Guillaume'
هر عبارت Groovy معتبر است، همانطور که در این مثال با یک عبارت حسابی می بینیم:
def sum = "The sum of 2 and 3 equals ${2 + 3}" assert sum.toString() == 'The sum of 2 and 3 equals 5'
نه تنها عبارات بین {}$ مجاز هستند، بلکه دستورات نیز مجاز هستند. با این حال، مقدار یک عبارت صفر است. بنابراین اگر چندین عبارت در آن حافظه جا درج شده باشد، جمله آخر باید به طریقی یک مقدار معنی دار را بازگرداند. به عنوان مثال، عبارت “The sum of 1 and 2 is equal to ${def a = 1; def b = 2; a + b}” پشتیبانی می شود و مطابق انتظار عمل می کند. یک روش خوب معمولاً رعایت اصطلاحات ساده در داخل متغیرهای GString است.
علاوه بر{}$ ، ما همچنین می توانیم از یک علامت $ تنها برای پیشوند یک عبارت نقطه دار استفاده کنیم:
def person = [name: 'Guillaume', age: 36] assert "$person.name is $person.age years old" == 'Guillaume is 36 years old'
اما فقط عبارات نقطه ای شکل a.b، a.b.c معتبر هستند. عبارات حاوی پرانتز مانند متد تماس، آکولادها، نقاطی که بخشی از ویژگی ها را بیان می کنند و یا عملگرها نامعتبر هستند. با توجه به تعریف متغیر یک عدد را مشاهده می فرمایید:
def number = 3.14
عبارت زیر یک groovy.lang.MissingPropertyException را نشان می دهد زیرا Groovy فکر می کند که شما سعی دارید به ویژگی toString آن شماره دسترسی پیدا کنید، که وجود ندارد:
shouldFail(MissingPropertyException) { println "$number.toString()" }
در نظر داشته باشید عبارت “$ number.toString ()” توسط تجزیه کننده به عنوان “$ {number.toString} ()” تفسیر می شود.
به همین ترتیب، اگر عبارت مبهم است، باید پرانتزها را نگه دارید:
String thing = 'treasure' assert 'The x-coordinate of the treasure is represented by treasure.x' == "The x-coordinate of the $thing is represented by $thing.x" // <= Not allowed: ambiguous!! assert 'The x-coordinate of the treasure is represented by treasure.x' == "The x-coordinate of the $thing is represented by ${thing}.x" // <= Curly braces required
اگر می خواهید از متغیرهایی $ یا {}$ در یک GString استفاده کنید تا ظاهر آنها درهم نشوند، برای قرار دادن علامت دلار فقط باید از یک کاراکتر \ استفاده کنید:
assert '$5' == "\$5" assert '${name}' == "\${name}"
مورد خاص تفسیر عبارات بسته شدن
تاکنون، ما در آموزش زبان برنامه نویسی groovy تهیه شده توسط آی تی پورت مشاهده کرده ایم که می توانیم عبارات دلخواه را در داخل {}$ استفاده کنیم، اما یک مورد خاص در مورد علامت گذاری برای عبارات بسته وجود دارد. وقتی نگهدارنده دارای یک پیکان است مانند:$ {→}، این عبارت در واقع یک عبارت بسته است – شما می توانید آن را به عنوان یک علامت بسته شدن در نظر بگیرید که کاراکتر دلار در مقابل آن قرار دارد:
- کروشه یک عبارت بدون پارامتر است که هیچ مقداری نمی گیرد.
- در اینجا، کروشه فقط یک آرگومان java.io.StringWriter را به خود می گیرد، که می توانید محتوا را با عملگر << leftShift اضافه کنید. در هر صورت، هر دو متغیرهایی بسته هستند.
از نظر ظاهری، به نظر می رسد مثال بالا یک روش طولانی برای تعریف عباراتی است که باید درون یابی شود، اما کروشه ها یک مزیت جالب نسبت به عبارات صرف دارند: lazy evaluation.
بیایید نمونه زیر را در نظر بگیریم:
- ما یک متغیر عددی حاوی ۱ را تعریف می کنیم که سپس آن را درون دو GStrings قرار می دهیم. یکی به عنوان یک عبارت در eagerGString و دیگری به عنوان کروشه در lazyGString.
- انتظار داریم رشته حاصل، همان رشته قسمت ۱ را برای eagerGString داشته باشد.
- به همین ترتیب برای lazyGString نیز همین انتظار را داریم.
- سپس مقدار متغیر را به عدد جدیدی تغییر می دهیم.
- با یک عبارت درونی ساده، این مقدار در زمان ایجاد GString محدود می شود.
- اما با یک عبارت کروشه، با هر بار اجرا، GString را به String فراخوانی می کند، و نتیجه آن یک رشته به روز شده حاوی عدد جدید است.
یک عبارت تعبیه شده درون کروشه و با بیش از یک پارامتر، در زمان اجرا یک استثنا ایجاد می کند. فقط کروشه با یک صفر و یا یک پارامتر مجاز است.
پیاده سازی قابلیت تعامل( Interoperability ) با جاوا
در آموزش زبان برنامه نویسی groovy، وقتی متدی (چه در جاوا و چه در Groovy) از java.lang.String استفاده می کند و ما نمونه ای از groovy.lang.GString را منتقل می کنیم، متد toString () GString به طور خودکار و شفاف فراخوانی می شود.
- ما یک متغیر GString ایجاد می کنیم.
- ما دوباره بررسی می کنیم که این نمونه ای از GString است.
- سپس ما آن GString را به متدی می دهیم که یک رشته را به عنوان پارامتر در نظر می گیرد.
- متد ()takeString به صراحت می گوید پارامتر آن تنها یک رشته است.
- ما همچنین بررسی می کنیم که این پارامتر در واقع یک رشته است و نه یک GString.
هش کدهای GString و String
اگرچه به جای رشته های ساده جاوا می توان از رشته های درون یابی استفاده کرد، اما آنها چند تفاوت خاص دارند: کد های hash آنها متفاوت است. رشته های جاوا تغییرناپذیر هستند، در حالیکه نمایش رشته ای GString در نتیجه، بسته به مقادیر درون یابی آن ممکن است متفاوت باشد.
assert "one: ${1}".hashCode() != "one: 1".hashCode()
از GString و رشته هایی که دارای مقادیر مختلف hashCode هستند، به عنوان کلیدهای نقشه استفاده نشود، خصوصاً اگر بخواهیم مقدار مرتبط را با یک رشته به جای GString بازیابی کنیم.
- نقشه با یک جفت اولیه ایجاد می شود که کلید آن GString است.
- وقتی می خواهیم مقدار را با یک کلید String واکشی کنیم، آن را پیدا نخواهیم کرد، زیرا Strings و GString دارای مقادیر مختلف کد هش هستند.
رشته سه گانه
در آموزش زبان برنامه نویسی groovy، رشته های سه گانه مانند رشته های دو گانه رفتار می کنند، علاوه بر این مانند رشته های سه گانه تک نقل شده چند رشته ای هستند.
def name = 'Groovy' def template = """ Dear Mr ${name}, You're the winner of the lottery! Yours sincerly, Dave """ assert template.toString().contains('Groovy')
نیازی به استفاده از نقل قول های مضاعف و نقل قول های منفرد در رشته های سه گانه و دوگانه نیست.
رشته های Slashy
در این قسمت از آموزش زبان برنامه نویسی groovy علاوه بر رشته های معمول نقل شده، رشته های بریده بریده شده نیز ارائه می شود، که از آنها به عنوان جدا کننده استفاده می کند. رشته های مضاف مخصوصاً برای تعریف اصطلاحات و الگوهای منظم بسیار مفید هستند.
نمونه ای از یک رشته بریده بریده یا Slashy:
def fooPattern = /.*foo.*/ assert fooPattern == '.*foo.*'
فقط اسلش های جلو باید بصورت برعکس قرار بگیرند:
def escapeSlash = /The character \/ is a forward slash/ assert escapeSlash == 'The character / is a forward slash'
نمونه ای از اجرای رشته بریده بریده شده به صورت چند خطی:
def multilineSlashy = /one two three/ assert multilineSlashy.contains('\n')
رشته های Slashy را می توان بعنوان راهی دیگر برای تعریف GString در نظر گرفت. بنابراین آنها از درون یابی نیز پشتیبانی می کنند:
def color = 'blue' def interpolatedSlashy = /a ${color} car/ assert interpolatedSlashy == 'a blue car'
موارد خاص
در قسمت رشته های آموزش زبان برنامه نویسی groovy ، یک رشته بریده بریده خالی را نمی توان با یک // نشان داد، زیرا توسط تجزیه کننده Groovy به عنوان یک خط نظر خط شناسایی می شود. به همین دلیل است که کد زیر در واقع کامپایل نمی شود:
assert '' == //
از آنجا که رشته های بریده بریده بیشتر به منظور سهولت در استفاده از regexp طراحی شده اند، بنابراین مواردی که در GStrings مانند $ (یا $ ۵) خطا هستند، با رشته های بریده بریده کار می کنند.
به یاد داشته باشید که نیازی به استفاده از بک اسلش نیست. یک روش جایگزین برای این مورد وجود دارد. رشته بریده بریده /\t\ یک بک اسلش است که کاراکتر “t” آن را دنبال می کند. و فقط برای نویسه اسلش مجاز است، به عنوان مثال /\/folder/ یک رشته بریده بریده حاوی ‘/folder’ خواهد بود. یک نتیجه استفاده از اسلش این است که یک رشته بریده بریده نمی تواند با یک بک اسلش پایان یابد. درعوض می توانید از یک ترفند ویژه استفاده کنید: /ends with slash ${‘\’}/ اما بهتر است از رشته بریده بریده شده در چنین شرایطی استفاده نکنید.
رشته Dollar slashy
رشته های Dollar slashy، یک GStrings چند خطی هستند که با $ / شروع و با / $ محدود می شوند. کاراکتر مورد استفاده علامت دلار است و می تواند از کاراکتر دلار دیگر، یا یک برش استفاده نمود.
مثالی در اینجا:
def name = "Guillaume" def date = "April, 1st" def dollarSlashy = $/ Hello $name, today we're ${date}. $ dollar sign $$ escaped dollar sign \ backslash / forward slash $/ escaped forward slash $$$/ escaped opening dollar slashy $/$$ escaped closing dollar slashy /$ assert [ 'Guillaume', 'April, 1st', '$ dollar sign', '$ escaped dollar sign', '\\ backslash', '/ forward slash', '/ escaped forward slash', '$/ escaped opening dollar slashy', '/$ escaped closing dollar slashy' ].every { dollarSlashy.contains(it) }
این مجموعه برای غلبه بر برخی از محدودیت های قوانین نادیده گرفتن رشته ایجاد شده است. وقتی قوانین آن متناسب با محتوای رشته شما باشد، می توانید از آن استفاده کنید (معمولاً اگر دارای چند برش باشد که نمی خواهید آنها را نادیده بگیرید).
جدول خلاصه رشته ها
کاراکتر ها
در ادامه آموزش زبان برنامه نویسی groovy به این نتیجه می رسیم که بر خلاف جاوا، Groovy کاراکتر واضحی ندارد. با این حال، می توانید صریحاً در مورد تبدیل یک رشته Groovy به یک کاراکتر واقعی، سه روش مختلف بیان کنید:
- هنگام اعلام کاراکتر آن را از نوع char در نظر می گیرد.
- استفاده از عملگر as
- استفاده از عملگر به کاراکتر
گزینه ۱ هنگامی جالب است که کاراکتر در یک متغیر نگه داشته شود، در حالی که دو مورد دیگر (۲ و ۳) جالب تر هستند وقتی که یک مقدار char باید به عنوان آرگومان فراخوانی متد منتقل شود.