אייפל (שפת תכנות) – הבדלי גרסאות

תוכן שנמחק תוכן שנוסף
GrouchoBot (שיחה | תרומות)
מ r2.7.2) (בוט מוסיף: an, ca, cs, da, de, eo, es, fi, fr, gl, hu, it, ja, ka, nl, pl, pt, ru, sk, uk, zh
הרחבת הערך נלקח מעבודתם של דניאל קלטר, הראל ולך, ציפורה זייני, ואילנה אלקובי - באדיבות מכון לב ומכון טל במסגרת קורס עקרונות שפות תוכנה
שורה 1:
'''אייפל''' ('''Eiffel''') היא שפת [[תכנות מונחה עצמים]]. שפה זו נוצרה בידי [[ברטנארד מאייר]] (שהיה חסיד של תכנות מונחה עצמים) ועל ידי חברת Eiffel Software ב-[[1985]]. ונקראה על שם [[גוסטב אייפל]], המהנדס שתכנן את [[מגדל אייפל]].
 
השפה נועדה לשפר שפות OOP קודמות. כתיבת השפה הושפעה מהשפות Simula, Ada , Z ושימשה השראה לשפות פופולאריות כמו: C# [[Java]] ,[[Ruby]] ,D. מושגים רבים שהוצגו לראשונה על ידי אייפל, לאחר מכן מצאו את דרכם לשפות תכנות מודרניות כ-#Java, C ושפות אחרות.
 
== מאפיינים עיקריים ==
 
* יבילות - רץ על פלטפורמות שונות.
* Melting ice - שילוב של הידור ומפרש שרץ ב-byte Code.
* Design by contract - יצירת חוזה.
* טיפוסיות חזקה (strong type) ללא המרות מרומזות.
* קישור דינמי (dynaic bounding) בזמן ריצה. מאפשר [[פולימורפיזם]].
* יבילות - רץ על פלטפורמות שונות.
* קריאות - מנגנונים ללוגיקה, מבניות בקוד ותיעוד.
* statically typed - מצריכה הגדרה בזמן קומפילציה.
* דוקומנטציה אוטומטית.
* מחלקות גנריות - מאפשרת שימוש במחלקות גנאריות.
* העמסת שיטות (Meyhod overloading) - ניתן לבצע חפיפת מתודות של השפה.
* העמסת אופרטורים (Operators overloading) - ניתן לבצע חפיפת אופרטורים של השפה.
* Pointer Arithmetic לא קיים בשפה.
* [[ביטוי רגולרי|ביטויים רגולריים]] לא קיים בשפה.
 
==עקרונות עיקריים==
 
===design by contract===
"חוזה" שמוגדר ע"י המתכנת, המגדיר את כל הממשק וההשפעות של התוכנית על סביבתה, בכך ניתן להקל על כל מי שרוצה להשתמש בצורה הכי בטוחה והכי יעילה. העיקרון הומצא על ידי ממציא השפה וזאת אחת התכונות החשובות של השפה.
לכל פונקציה ניתן להצהיר:
:תנאים לפני הרצת הפונקציה (Pre Conditions)
:תנאים לאחר הרצת הפונקציה (Post Conditions)
:מה מותר ואסור לתת לפונקציה בפרמטרים
:מה מותר ואסור לפונקציה להחזיר
:מה מותר ואסור לפונקציה לזרוק (exception)
:תופעות לוואי של הרצת הפונקציה (לדוגמה שימוש בלולאה לצורך השהייה)
:נתונים על הביצועים שלה (זיכרון, זמן ריצה)
:ביטויים קבועים לאורך התוכנית (Invariant)
 
design by contract הינו סימן רשום של Eiffel software והמונח הוטמע והומצא ע"י ד"ר ברנרד מאייר יוצר השפה ולכן "החוזה" הינו חלק מאוד מרכזי בשפת אייפל.
 
 
==== דוגמא ל design by contract class DATE ====
 
<source lang="eiffel">
create
make
feature {NONE}
-- Initialization
make (a_day: INTEGER; a_hour: INTEGER) -- Initialize `Current' with `a_day' and `a_hour'.
require
valid_day: 1 <= a_day and a_day <= 31
valid_hour: 0 <= a_hour and a_hour <= 23
do
day&nbsp;:= a_day
hour&nbsp;:= a_hour
ensure
day_set: day = a_day
hour_set: hour = a_hour
end
feature -- Access
day: INTEGER -- Day of month for `Current'
hour: INTEGER -- Hour of day for `Current'
feature -- Element change
set_day (a_day: INTEGER) -- Set `day' to `a_day'
require
valid_argument: 1 <= a_day and a_day <= 31
do
day&nbsp;:= a_day
ensure
day_set: day = a_day
end
invariant
valid_day: 1 <= day and day <= 31
valid_hour: 0 <= hour and hour <= 23
end
</source>
 
===Open Closed principle===
קוד צריך להיות פתוח להרחבה וסגור לשינויים זה יכול להתבטא בשתי צורות:
בצורה שזה מתבטא בשפה שלנו - כותבים מחלקה בצורה רגילה, ואם מתגלה באג בתוכנה, אז במקום לשנות את המחלקה המקורית יוצרים מחלקה חדשה שמשתמשת במחלקה הקודמת ועושה את השינויים שנצרכים, או שעושים מחלקה שיורשת מהמחלקה המקורית ושם עושים את השינויים.
בצורה הרגילה שימוש במחלקה אבסטרקטית וירושות ממנה בצורה כזאת שכולם צריכים להיות באותה התבנית ואז מקשרים את כולם בפולימורפיזם.
 
===uniform access principle===
מכיוון שיש שינויים ותוספות של אובייקטים חדשים לשפה, דאגו לעשות שכל הפניות יהיו באותה צורה כדי לחסוך תקלות. ולכן יש מנגנון גישה זהה לכל הפונקציות והמחלקות.
לדוגמא:
(Foo.bar(5
יכול לשמש בתור פונקציה שמקבלת את הערך 5 ויכול גם לשמש בתור מחלקה שהמשתנה שלה יקבל את הערך 5.
 
===Command Quiery seperetion===
הפרדה מוחלטת בין פונקציה שמחזירה ערך כלומר בקשת מידע ואשר אינה יכולה בשום אופן לעדכן מידע לבין פרוצדורה המעדכנת או מבצעת פעולה אך אינה מחזירה מידע וזאת ע"מ לא ליצור side effects שלא התכוונת אליהם.
תאימות
 
===תאימות לשפות אחרות===
השפה בנויה כך שתוכל להתממשק בקלות עם מגוון שפות (בדגש על שפת [[C]] ודוט נט) אפשר אפילו לכתוב קוד בשפת C בגוף הפונקציה של Eiffel ובכך להשלים כל חיסרון שעלול להיות בשפה עם הסיפריות של שפת C.
 
==ניהול זיכרון==
ניהול זיכרון של תוכנית בשפת Eiffel הינה משימה לא קלה בגלל שלוש סיבות:
תוכנית בשפת Eiffel יכולה לקרוא לפונקציות בשפת C, לכן צריך להתחשב בכך שיכולות להיות בתוכנית 2 סוגי זיכרון: זכרון ל-Eiffel וזיכרון ל-C.
צריך להבחין בין אובייקטים רגילים - אובייקטים בעלי גודל קבוע שנקבע באופן סטטי (בזמן הקומפילציה) עפ"י מספר תכונות האובייקט - לבין אובייקטים מיוחדים - אובייקטים בעלי גודל משתנה (מערכים, מחרוזות ועוד...).
לא מספיק לשחרר זיכרון רק לשם שימוש חוזר בתוכניות בשפת Eiffel, אלא אנו מעוניינים שניתן יהיה להחזיר את הזיכרון אל מערכת ההפעלה לשימוש חוזר גם באפליקציות אחרות.
מסיבות אלה, Eiffel אינה מסתפקת ב- syscall malloc() (שכן malloc() לא יכול להחזיר את הזיכרון אל מערכת ההפעלה), אלא יש לה מנגנון לניהול זיכרון משלה.
כמו כן, על מנת לפתור את בעיית ה-Garbage Collection, השפה אינה מסתפקת באלגוריתם מוכן לביצוע Garbage Collection, אלא היא משתמשת בכמה אלגוריתמים בסיסיים, ובכל פעם שיש צורך ב GC, האלגוריתם נקבע לפי הנסיבות ורמת הדחיפות.
 
שתי האלגוריתמים העיקריים למימוש GC בשפת Eiffel, הם:
* Mark & Sweep
* Memory Compaction
כברירת מחדל, כל יישום בשפת Eiffel כולל GC אוטומטי. אבל בכל אופן ניתן לשלוט על מנגנון ניהול זיכרון ולכוון אותו כך שיתאים לצרכים הספציפיים של המתכנת באמצעות פונקציות ופרוצדורות השייכות למחלקה MEMORY, שמאפשרים "להדליק" או "לכבות" את ה GC האוטומטי.
המאפיין הייחודי של ה-GC של Eiffel הוא שה GC אינו מבצע שחרור זיכרון רק עבור שימוש חוזר ע"י הקצאת אובייקטים נוספים לאותה תכנית, אלא למעשה, מחזיר את הזיכרון למערכת ההפעלה ומשחרר אותו לשימוש חוזר ע"י תכנית אחרת. למרות שקשה ליישם את המאפיין החשוב הזה, הוא הכרחי בעיקר למערכות שצריכות לרוץ במשך הרבה זמן או אפילו באופן קבוע.
 
 
== שפה ==
 
=== משתנים פשוטים ===
 
נקראים גם EXPANDED
 
מצד שמאל השם של הטיפוס מצד ימין הטיפוס:
 
<source lang="eiffel">flag: BOOLEAN
 
i: INTEGER
 
s: STRING
 
r:REAL
 
d:DOUBLE
 
c:CHARACTER</source>
 
=== אובייקטים ===
 
נקראים גם REFERENCE ומכילים אוביקטים או מערכים לדוגמא אובייקט שאני הגדרתי(אלא אם כן הגדרתי במפורש EXPEND):
 
<source lang="eiffel">i: MYoBJ</source>
 
=== ערכים דפולטיבים ===
 
{| cellspacing="1" cellpadding="1" border="1" align="center" style="width: 284px; height: 200px;"
|-
! scope="col" | <br/>
! scope="col" | ערך<br/>
! scope="col" | משתנה<br/>
|-
| 1<br/>
| align="center" valign="middle" | 0<br/>
| align="center" valign="middle" | INTEGER<br/>
|-
| 2<br/>
| align="center" valign="middle" | 0<br/>
| align="center" valign="middle" | REAL<br/>
|-
| 3<br/>
| align="center" valign="middle" | 0<br/>
| align="center" valign="middle" | DOUBLE<br/>
|-
| 4<br/>
| align="center" valign="middle" | FALSE<br/>
| align="center" valign="middle" | BOOLEAN<br/>
|-
| 5<br/>
| align="center" valign="middle" | NULL<br/>
| align="center" valign="middle" | CHARACHTER<br/>
|-
| 6<br/>
| align="center" valign="middle" | VOID REFERENCE<br/>
| align="center" valign="middle" | REFERANCE TYPE<br/>
|}
 
=== מערכים - ARRAY ===
 
הצהרה:&nbsp;
 
<source lang="eiffel">keywords : ARRAY[STRING]
numbers: ARRAY[INTEGER]</source>
 
יצירה(מערך מ1 עד 100):
 
<source lang="eiffel">create keywords.make(1,100)</source>
 
=== רשומה ===
 
נקרא tuples מקבילה של struct או class ללא פונקציות רק data members:
 
<source lang="eiffel">
 
t: TUPLE [name: STRING; weight: REAL; date: DATE]
 
</source> יכול להוות תאריך או רשומה מסויימת וא"צ להגדיר מחלקה <source lang="eiffel">
 
["Brigitte", 3.5, Last_night]
 
</source>
 
גישה: <source lang="eiffel">
 
t.weight := t.weight + 0.5
 
</source>
 
=== אופרטורים ===
 
{| border="1" align="center" width="200"
|-
! scope="col" | <br/>
! scope="col" | שם<br/>
! scope="col" | סימן<br/>
|-
| 1<br/>
| גדול<br/>
| align="center" valign="middle" | <<br/>
|-
| 2<br/>
| קטן<br/>
| align="center" valign="middle" | ><br/>
|-
| 3<br/>
| שווה<br/>
| align="center" valign="middle" | =<br/>
|-
| 4<br/>
| שונה<br/>
| align="center" valign="middle" | =/<br/>
|-
| 5<br/>
| גדול שווה<br/>
| align="center" valign="middle" | =<<br/>
|-
| 6<br/>
| קטן שווה<br/>
| align="center" valign="middle" | =><br/>
|-
| 7<br/>
| השמה<br/>
| align="center" valign="middle" | =:<br/>
|}
 
=== IF ===
 
'''if''' תנאי
'''then''' גוף
'''else''' אם לא מתקיים התנאי
'''end''' סוף תנאי
 
<source lang="eiffel">if(num>10)
 
then
 
output.putint (num)
 
output.new_line
 
else
 
output.putstring ("Error")
 
end</source>
 
=== LOOP ===
 
'''from''' תנאי התחלה
'''until''' תנאי עצירה
'''loop/end''' גוף הלולאה
 
<source lang="eiffel">from
 
I:=0
 
until
 
I>10
 
loop
 
RESULT := RESULT + 1
 
end</source>
 
===פונקציות ופרוצדורות===
ישנה הסכמה בשפה לגבי הפרדה גמורה בין פונקציות לבין פרוצדורות.
:פונקציות - עושות חישובים ומחזירות ערך, אבל לא יכולות לבצע שינויים במשתנים.
:פרוצדורות - עושות שינויים במשתנים אבל לא מחזירות ערך.
בצורה כזאת, אפשר לשלוח פונקציה בלי לדאוג שישתנו דברים בתוכנית. אך בפועל בשפה הקומפיילר לט אוכף נושא זה.
שם הפונקציה בסוגרים פרמטרים ואחרי ערך מוחזר (אפשר להשמיט ערך מוחזר או פרמטרים או שניהם) הIS מכיל הערה שמתארת את הפונקציה.
 
=== CLASS ===
 
תוכנית אייפל ידועה כמערכת, ומרכיביה הינן מחלקות. יכול להיות מספר כלשהו של מחלקות במערכת. רבות מהן מחלקות כלליות. וחלקן מחלקות השייכות למערכת. המערכת פיתוח אייפל מגיעה עם ספריות עם מחלקות מובנות בעלות יעוד. מחלקות בסיסיות רבות מוגדרות בשפה,והן חייבות להופיע.
 
*'''note''' - הערות המחלקה
*'''class''' - שם המחלקה
*'''inherit''' - ממי יורש (אופציונלי)
*'''create''' - פונקציות מאתחלות
*'''local''' - משתני מחלקה
*'''do-end''' - גוף המחלקה
 
 
<source lang="eiffel">note
 
description : "targil5 application root class"
 
date : "$Date$"
 
revision : "$Revision$"
 
class
 
APPLICATION
 
inherit
 
ARGUMENTS
 
create
 
make
 
feature {NONE} -- Initialization
 
make
 
-- Run application.
 
local
 
cmp : JCOMPILER
 
do
 
cmp.make
 
end
 
end</source>&nbsp;
 
 
== מנגנון ניהול חריגות ==
לשפה יש מנגנון מאוד יעיל של ניהול חריגות שעובד בצורה כזאת שהוא משתמש בבדיקת הpost condition שלו, ובמקרה שזה לא עובר, הוא עושה את הפונקציה מחדש בשביל לנסות שוב לפי מספר הניסיונות שהוגדרו לו מראש.{{ש}}לדוגמא: <source lang="eiffel">
connect_to_server (server: SOCKET) -- Connect to a server or give up after 10 attempts. require
None_Null: server /= Void and then server.address /= Void
local
attempts: INTEGER
do
server.connect
ensure
connected: server.is_connected
rescue
if attempts < 10 then
attempts := attempts + 1
retry
end
end
</source>
 
 
==אפשרויות שונות בשפה==
קריאות חד פעמיות - משמש לאיפוס ערכים באובייקטים ועובד בצורה קלה ונוחה.
 
מנגנון ניהול חריגות - לשפה יש מנגנון מאוד יעיל של ניהול חריגות שעובד בצורה כזאת שהוא משתמש בבדיקת הpost condition שלו, ובמקרה שזה לא עובר, הוא עושה את הפונקציה מחדש בשביל לנסות שוב לפי מספר הניסיונות שהוגדרו לו מראש.
 
השפה משלבת שתי גישות לתרגום – יש לה גם מפרש, וגם מהדר.
קוד שלא נעשה בו שינוי מאז הפעם האחרונה, כולל ספריות מערכת, הוא קוד שעבר הידור – ולכן הוא "קפוא".
קוד ששונה "הותך", ועל ההרצה שלו מופקד המפרש של השפה.
היתרון של הטכנולוגיה, הוא שהיא נותנת לנו להנות מכל העולמות - מהירות הריצה שמספק קוד שכבר תורגם במלואו לשפת מכונה ע"י המהדר, ומהירות תגובה לשינויים בעזרת קוד מפורש.
 
==תרגום לשפת מכונה==
כמו ב Java, באייפל יש שני שלבי תרגום:
 
החלק הראשון הוא תרגום לקוד ביניים בעזרת מהדר, עליו רץ מפרש.
אח"כ, הקוד מתורגם לשפת C, ובעזרת מהדר C הוא מתורגם לשפת מכונה.
 
ע"פ מתכנני השפה, מטרת התרגום לשפת C כשפת ביניים, הוא ניצול שיטות הייעול הקיימות במהדרי שפת C. (לטענת מעצבי השפה, קוד בשפת Eiffel יכול להיות יעיל כאילו נכתב בשפת C עצמה או Fortran)
 
== חווית המשתמש ==
התוכנה מתאימה לכותבים שצריכים לתאם ביניהם ממשקים, או שהשימוש בקוד לא ידוע מראש (ירושה מבוקרת).
ה- writeabilty סביר, דרוש מעט זמן להתרגל לשפה, וכן יש הרבה דוקומנטציה על השפה היתרון הוא שהוא מפורט והחיסרון שהוא כמעט היחיד (עיין למטה בקישורים)
 
==הערות כלליות==
 
*השפה הינה case insensitive - הקומפיילר אינו מבחין בין אותיות גדולות וקטנות, זאת אומרת שלא משנה אם כותבים InTeGer או iNtEgEr. אבל... בכל מקרה יש סגנון כתיבה קבוע לשפה כדי לעשות את הקוד קריא לכל מי שמכיר את השפה. ולכן נוהגים לכתוב: מחלקות - באותיות גדולות, פונקציות - באותיות קטנות, משתנים - אות ראשונה גדולה והשאר קטנות, מספר מילים - כותבים עם קו תחתון בין המילים.
 
* באייפל אין חובה לשים נקודה פסיק (;) בסוף שורה
* יש להבדיל בין אופרטור שוה (=) שמחזיר ערך בוליאני ואינו מבצע השמה לבין אפרטור השמה (=:)
* הסימן -- (מינוס כפול) מבטא הערה
* פונקציות יצירה הם סוג של פונקציות בונות (אלא שקוראים להן אקטיבית) המשמשות לאיתחול והגדרות המחלקה יש להגדיר פונקציות כאלה בחלק CREATE במחלקה ולממשן בחלק FEATURS כמו כל שאר הפונקציות
* חלק IS בהגדרת הפונקציה מכיל הערה הממצה את מהות ה מחלקה ("מטפורה")
* פונקציות נקראות בדומה למשתנים ולכן המשתמש לא צריך לדעת את אופן המימוש.
* השפה מאד מבנית, משתמשת בבלוקים לכל קבוצת קוד. בדומה לADA
 
==בעיות ופתרונן==
 
*כאשר פונקציה מחזירה פרמטר יש להשתמש בפרמטר המובנה בשפה RESULT לצורך החזרה.
*אין נגישות למערך אחרי הגדרתו. יש לעשות CREATE לאובייקטים כגון מערכים, קבצים וכו'.
*בטיפוס מסוג אובייקט בצורה דפולטיבית השמה מחזיר פוינטר לאובייקט ולכן אם הוא נמחק קיים פוינטר מתנדנד ולכן רצוי להשתמש ב בCLONE או COPY
* קיים קושי במציאת מדריך שפשוט מראה פקודות ולא רק מדבר על תיאוריה של השפה.
* פתיחת קבצים נעשית בצורה שונה מתוכניות אחרות, צריך להכניס את מיקום הקובץ למשתנה ורק אחרי זה להתחיל לפעול עליו.
* מערכת שונה של החזרת ערך מהפונקציה במקום לעשות return מכניסים את הערך שרוצים אל המשתנה result. (בדומה לPL/SQL)
 
== פלטפורמות==
אייפל רצה על הפלטפורמות הבאות: Windows ,Linux, Unix ,VMS.
 
==קומפיילרים==
 
*smartEiffel - בקישור [http://smarteiffel.loria.fr/ קומפיילר חינמי קוד פתוח מתאים לכל מחשב ANSI C.]
*visual eiffel - מסחרי IDE כולל GUI עובד על Win32, linux. כאן: [http://visual-eiffel.com]
*EiffelStudio - חינמי IDE מתקדם כולל GUI אחד העורכים המתקדמים אפשר למצוא כאן: [http://sourceforge.net/projects/eiffelstudio/?source=directory] ,זוהי הסביבת פיתוח הכי עדכנית כולל debuger והשלמה אוטומטית.כמו כן, יש בו יוצר תיעוד ותרשים מערכת(class Diagram).
 
[[קטגוריה:תכנות מונחה-עצמים]]