אובייקטים ומחלקות

‫‪1‬‬
‫אובייקטים ומחלקות‬
‫הגדרת ‪ class‬והגדרת ‪struct‬‬
‫הגדרת משתנים‬
‫הגדרת מתודות‬
‫הגדרת ‪properties‬‬
‫הגדרת ‪constructors‬‬
‫משתנים מסוג ‪Read Only‬‬
‫הגדרת מחלקה אנונימית‬
‫הגדרת ‪struct‬‬
‫הגדרת מחלקה מסוג ‪partial‬‬
‫הגדרת מחלקה סטטית‬
‫המחלקה ‪Object‬‬
‫‪© 2009 Haim Michael‬‬
‫‪2‬‬
‫הגדרת ‪ class‬והגדרת ‪struct‬‬
‫הגדרת ‪ class‬ב‪ C#-‬מהווה הגדרה של תבנית שעל פיה ניתן לאחר מכן לייצור אובייקטים‪ .‬בתבנית יוגדו משתנים‬
‫ומתודות‪ .‬בכל אחד מהאובייקטים שייווצרו על פיה ניתן יהיה למצוא את כל אחד מהמשתנים‪ .‬את כל אחת מהמתודות‬
‫ניתן יהיה להפעיל על כל אחד מהאובייקטים‪.‬‬
‫הגדרה של ‪ struct‬דומה במשמעותה להגדרה של ‪ .class‬ההבדל הוא בכך שהזיכרון שמשמש ליצירת אובייקטים מ‪-‬‬
‫‪ struct‬נלקח מה‪ stack-‬בעוד שהזיכרון שמשמש ליצירת אובייקטים מ‪ class-‬נלקח מה‪ .heap-‬הבדל נוסף הוא שלא ניתן‬
‫להגדיר ‪ struct‬אשר יורש מ‪ struct-‬אחר‪.‬‬
‫כללי התחביר שחלים בהגדרה של ‪ class‬דומים לכללי התחביר שחלים בהגדרה של ‪ .struct‬ההבדל הוא שבמקום‬
‫להשתמש במילה ‪ class‬משתמשים במילה ‪.struct‬‬
‫‪© 2009 Haim Michael‬‬
‫‪3‬‬
‫הגדרת משתנים‬
‫יצירת אובייקט חדש מ‪ class-‬או מ‪ struct-‬נעשית באמצעות המילה השמורה ‪ .new‬גישה למשתנים שבתוך האובייקט‬
‫נעשית באמצעות אופרטור הנקודה '‪ ,'.‬אשר משמש גם לקריאה להפעלתן של מתודות )על האובייקט(‪.‬‬
‫;)‪Rectangle rec = new Rectangle(20,30‬‬
‫;‪rec.width = 20‬‬
‫;‪rec.height = 30‬‬
‫;)(‪double val = rec.Area‬‬
‫משתנים סטטיים מוגדרים באמצעות המילה השמורה ‪ .static‬להבדיל ממשתנה רגיל אשר ניתן יהיה למצוא בכל אחד‬
‫מהאובייקטים‪ ,‬משתנה סטטי מתאר את המחלקה כולה והוא איננו מופיע בעותקים נפרדים בכל אחד מהאובייקטים‪ .‬כדי‬
‫לפנות למשתנה סטטי ניתן לרשום את שם המחלקה בצירוף אופרטור הנקודה המפרידה '‪ '.‬ומייד לאחריו שם המשתנה‬
‫הסטטי שאליו רוצים לפנות‪.‬‬
‫;‪Rectangle.MaxWidth = 100‬‬
‫‪© 2009 Haim Michael‬‬
‫‪4‬‬
‫הגדרת מתודות‬
‫ב‪ classs-‬ניתן להגדיר מתודות אשר ניתן יהיה להפעיל על כל אובייקט שיווצר ממנו‪ .‬הפעלת מתודה על אובייקט נעשית‬
‫באמצעות אופרטור הנקודה '‪.'.‬‬
‫;)‪Rectangle rec = new Rectangle(20,30‬‬
‫;‪rec.width = 20‬‬
‫;‪rec.height = 30‬‬
‫;)(‪double val = rec.Area‬‬
‫הגדרה של מתודה נעשית באופן הבא‪:‬‬
‫)]‪[modifiers] return_type MethodName([parameters‬‬
‫{‬
‫‪...‬‬
‫}‬
‫אם מוסיפים להגדרת המתודה את המילה השמורה ‪ static‬אז מתקבלת מתודה שלא ניתנת להפעלה על אובייקט‬
‫מסוים‪ .‬המתודה שמתקבלת מסוגלת לבצע פעולה כללית אשר קשורה למחלקה מבלי לפעול על אובייקט מסוים‪ .‬הדוגמה‬
‫הבאה מציגה הגדרה של מתודה סטטית‪.‬‬
‫‪© 2009 Haim Michael‬‬
5
using System;
namespace abelski.csharp
{
class SimpleMethodDemo
{
static void Main()
{
int value1 = 1234;
int value2 = 2222;
int value3 = Sum(value1,value2);
Console.WriteLine("value1="+value1);
Console.WriteLine("value2="+value2);
Console.WriteLine("value3="+value3);
Console.ReadLine();
}
}
static int Sum(int num1, int num2)
{
return num1 + num2;
}
}
:‫הפלט הוא‬
© 2009 Haim Michael
6
‫ אם מסמנים פרמטר של‬.(‫ )ברירת מחדל‬by value ‫כאשר מגדירים מתודה עם פרמטרים הערכים שיישלחו אליה יישלחו‬
‫ יש להוסיף גם להגדרת הפרמטר במתודה וגם לקוד אשר‬ref ‫ את‬.by reference ‫ אז הערך יישלח‬ref ‫מתודה באמצעות‬
.‫ הדוגמה הבאה מציגה זאת‬.‫קורא להפעלתה‬
using System;
namespace abelski.csharp
{
class ByReferenceDemo
{
static void Main()
{
int i = 2;
Console.WriteLine("before... i="+i);
DoSomething(ref i);
Console.WriteLine("after... i="+i);
Console.ReadLine();
}
static void DoSomething(ref int num)
{
num++;
}
}
}
:‫הפלט יהיה‬
© 2009 Haim Michael
‫‪7‬‬
‫ניתן להגדיר מתודה אשר מחזירה יותר מערך אחד באמצעות פרמטר שמוגדר בה‪ .‬כאשר משתמשים ב‪ ref-‬בהגדרתו של‬
‫פרמטר ניתן לקבל דרכו ערך מוחזר‪ .‬כאשר משתמשים ב‪ out-‬אז בדומה לשימוש ב‪ ref-‬ניתן לקבל באמצעות הפרמטר‬
‫ערך מוחזר‪ .‬ההבדל הוא שכאשר משתמשים ב‪ out-‬אז לא חייבים לאתחל את המשתנה אשר שולחים למתודה‪ .‬בדומה‬
‫לשימוש ב‪ ref-‬את ‪ out‬יש להוסיף גם להגדרת הפרמטר במתודה וגם לקוד אשר קורא להפעלתה‪ .‬הדוגמה הבאה מציגה‬
‫זאת‪.‬‬
‫;‪using System‬‬
‫‪namespace abelski.csharp‬‬
‫{‬
‫‪class OutParameterDemo‬‬
‫{‬
‫)(‪static void Main‬‬
‫{‬
‫;‪int i‬‬
‫;)‪DoSomething(out i‬‬
‫;)‪Console.WriteLine("i="+i‬‬
‫;)(‪Console.ReadLine‬‬
‫}‬
‫)‪static void DoSomething(out int num‬‬
‫{‬
‫;‪num=123‬‬
‫}‬
‫}‬
‫}‬
‫הפלט יהיה‪:‬‬
‫‪© 2009 Haim Michael‬‬
8
‫ ההבדל ביניהן חייב להיות במספר‬.‫ תומכת בהגדרה של מספר גרסאות שונות לאותה מתודה‬C# ‫שפת התיכנות‬
.‫ להלן דוגמה‬.(overloading methods) ‫או בטיפוס שלהם‬/‫הפרמטרים ו‬
using System;
namespace abelski.csharp
{
class OverloadingParametersDemo
{
static void Main()
{
int num1 = 20;
int num2 = 44;
int num3 = 24;
int num4 = Total(num1,num2,num3);
Console.WriteLine("num4="+num4);
Console.ReadLine();
}
static int Total(int val1, int val2)
{
return val1+val2;
}
static int Total(int val1, int val2, int val3)
{
return val1+val2+val3;
}
}
}
:‫הפלט יהיה‬
© 2009 Haim Michael
‫‪9‬‬
‫הגדרת ‪properties‬‬
‫שפת התיכנות ‪ C#‬מאפשרת להגדיר מתודה )או זוג של מתודות( אשר יפעלו מבחינת המתכנת באופן שקוף בכל פעם‬
‫שינסה לקבוע את ערכו )או לקבל בחזרה את ערכו( של משתנה שאליו המתודה )או זוג המתודות( מתייחסת )מתייחסות(‪.‬‬
‫מתודה )מתודות( זו )אלה( ידועה )ידועות( בשם ‪ .property‬אופן ההגדרה של ‪ property‬הוא כדלקמן‪.‬‬
‫‪public property_type PropertyName‬‬
‫{‬
‫‪access_modifier get‬‬
‫{‬
‫‪... return some value‬‬
‫}‬
‫‪access_modifier set‬‬
‫{‬
‫‪... set the property value‬‬
‫}‬
‫}‬
‫באמצעות ‪ value‬ניתן להתייחס לערך שאותו מנסים להכניס אל תוך המשתנה שה‪ property-‬מתייחס אליו‪ .‬ניתן‬
‫להשתמש ב‪ value-‬רק בגבולות של בלוק הפקודות שמתייחס ל‪ .set-‬הדוגמה הבאה ממחישה זאת‪.‬‬
‫;‪using System‬‬
‫‪namespace Abelski.CSharp‬‬
‫{‬
‫‪class SimplePropertyDemo‬‬
‫{‬
‫)(‪static void Main‬‬
‫{‬
‫;)(‪Rectangle rec = new Rectangle‬‬
‫;‪rec.Width=12‬‬
‫;‪rec.Height=14‬‬
‫;)(‪rec.PrintDetails‬‬
‫}‬
‫}‬
‫‪class Rectangle‬‬
‫;‪private double width, height‬‬
‫‪© 2009 Haim Michael‬‬
‫{‬
10
public void PrintDetails()
{
Console.WriteLine("["+Width+","+Height+"]");
}
public double Width
{
get
{
return width;
}
set
{
if(value>0) { width = value; }
else {Console.WriteLine("width was not set...");}
}
}
public double Height
{
get
{
}
set
{
return height;
if(value>0)
{
height = value;
}
else
{
Console.WriteLine("height was not set...");
}
}
}
}
}
© 2009 Haim Michael
‫‪11‬‬
‫הפלט הוא‪:‬‬
‫אם משמיטים את ‪ set‬מההגדרה של ה‪ property-‬אז מקבלים ‪ .read only property‬אם משמיטים את ‪get‬‬
‫מההגדרה של ה‪ property-‬אז מקבלים ‪ .write only property‬ניתן להעניק הרשאות גישה שונות ל‪ get-‬ול‪-‬‬
‫‪.set‬‬
‫אם ה‪ property-‬שאנו רוצים להגדיר הוא ‪ property‬פשוט ללא כל בדיקות אז ניתן להגדירו באופן המקוצר הבא‪:‬‬
‫};‪public property_type property_name {get; set‬‬
‫במקרה שבו מגדירים את ה‪ property-‬באופן זה אז אין צורך להגדיר את המשתנה שאליו ה‪ property-‬מתייחס‪.‬‬
‫המהדר יעשה זאת עבורנו באופן אוטומטי‪ .‬זהו המקרה היחידי שבו המשתנה מוגדר עבורנו באופן אוטומטי‪.‬‬
‫ניתן להגדיר את ‪ set‬ואת ‪ get‬עם הרשאות גישה שונות באופן הבא‪:‬‬
‫};‪public property_type property_name {get; private set‬‬
‫‪© 2009 Haim Michael‬‬
12
.properties ‫הדוגמה הבאה מציגה הגדרה מקוצרת של‬
using System;
namespace abelski.csharp
{
class AutomaticProperty
{
static void Main()
{
Rectangle rec = new Rectangle();
rec.Width=12;
rec.Height=14;
rec.PrintDetails();
}
}
class Rectangle
{
public void PrintDetails()
{
Console.WriteLine("["+Width+","+Height+"]");
}
public double Width {get; set;}
public double Height {get; set;}
}
}
:‫הפלט שיתקבל הוא‬
© 2009 Haim Michael
13
© 2009 Haim Michael
‫‪14‬‬
‫הגדרת ‪constructors‬‬
‫הגדרה של ‪ constructors‬ב‪ C#-‬נעשית באופן דומה להגדרה של ‪ constructors‬ב‪ .Java-‬הגדרה של ‪constructor‬‬
‫הנה‪ ,‬למעשה‪ ,‬הגדרה של מתודה עם שם שזהה לשם של המחלקה ומבלי שיהיה לה ערך מוחזר‪.‬‬
‫‪public class SomethingClass‬‬
‫{‬
‫)(‪public SomethingClass‬‬
‫{‬
‫‪...‬‬
‫}‬
‫}‬
‫כל עוד לא הגדרנו ‪ constructor‬מיוזמתנו‪ ,‬המהדר מייצר עבורנו ‪ ,default constructor‬שהינו‬
‫‪ constructor‬ללא כל פרמטרים‪ .‬בדומה להגדרה של מתודות‪ ,‬ניתן להגדיר יותר מ‪ constructor-‬אחד )‬
‫‪ .(constructors overloading‬ניתן להגדיר ‪ constructors‬עם כל הרשאת גישה‪.‬‬
‫שפת התכנות ‪ C#‬מאפשרת גם להגדיר ‪ static constructor‬באופן הבא‪:‬‬
‫‪class MyClass‬‬
‫{‬
‫)(‪static MyClass‬‬
‫{‬
‫‪...‬‬
‫}‬
‫}‬
‫ה‪ static constructor-‬חייב להיות מוגדר ללא כל פרמטרים‪ .‬ניתן להגדיר ‪ static constructor‬אחד‬
‫בלבד‪ .‬ה‪ static constructor-‬מתבצע פעם אחת בלבד )כאשר ה‪ class-‬נטען לזיכרון(‪ .‬ל‪static-‬‬
‫‪ constructor‬אין הרשאת גישה‪ .‬בהיותו מופעל פעם אחת בלבד כאשר ה‪ class-‬נטען לזיכרון אין כל משמעות‬
‫להרשאת גישה‪ .‬הדוגמה הבאה מציגה הגדרה של ‪.static constructor‬‬
‫‪© 2009 Haim Michael‬‬
15
using System;
namespace abelski.csharp
{
class StaticConstructorDemo
{
private static int defaultWidth;
private static int defaultHeight;
static StaticConstructorDemo()
{
defaultWidth = 10;
defaultHeight = 4;
}
}
}
static void Main()
{
Rectangle rec = new Rectangle();
rec.Width=defaultWidth;
rec.Height=defaultHeight;
rec.PrintDetails();
}
class Rectangle
{
public void PrintDetails()
{
Console.WriteLine("["+Width+","+Height+"]");
}
public double Width {get; set;}
public double Height {get; set;}
}
© 2009 Haim Michael
16
:‫הפלט שיתקבל הוא‬
:‫ אחר באופן הבא‬constructor ‫ מסוים ניתן לקרוא מתוכו להפעלתו של‬constructor ‫כאשר מופעל‬
class MyClass
{
public MyClass(int width): this(width,10)
{ ... }
public MyClass(int width, int height)
{ ... }
}
.‫הדוגמה הבאה מציגה זאת‬
using System;
namespace abelski.csharp
{
class ConstructorsThisDemo
{
static void Main()
{
Rectangle rec = new Rectangle();
rec.PrintDetails();
}
}
}
© 2009 Haim Michael
17
class Rectangle
{
private double Width {get; set;}
public double Height {get; set;}
public Rectangle() : this(10.0,10.0)
{
Console.WriteLine("Rectangle() is executed");
}
public Rectangle(double widthVal, double heightVal)
{
this.Width = widthVal;
this.Height = heightVal;
Console.WriteLine("Rectangle(double,double) executed");
}
public void PrintDetails()
{
Console.WriteLine("["+Width+","+Height+"]");
}
}
}
:‫הפלט שנקבל הוא‬
© 2009 Haim Michael
‫‪18‬‬
‫משתנים מסוג ‪Read Only‬‬
‫ניתן לסמן משתנה במחלקה באמצעות ‪ .readonly‬במקרה כזה‪ ,‬המקום היחידי שבו ניתן יהיה להכניס לתוכו ערך הוא ה‪-‬‬
‫‪ .constructor‬להבדיל ממשתנה מסוג ‪ ,constt‬ניתן לסמן משתנה כ‪ readonly-‬גם כשמדובר במשתנה ‪ static‬וגם‬
‫כשמדובר במשתנה ‪.instance‬‬
‫‪© 2009 Haim Michael‬‬
‫‪19‬‬
‫הגדרת מחלקה פנימית אנונימית‬
‫ניתן להגדיר מחלקה אנונימית )ללא שם( אשר יורשת מ‪ Object-‬והגדרתה משולבת ביצירת אובייקט ממנה באופן הבא‪:‬‬
‫{ ‪var stud = new‬‬
‫‪Name=”Daniel Shabat”,‬‬
‫‪id=2321231,‬‬
‫;}‪average=98‬‬
‫‪© 2009 Haim Michael‬‬
20
struct ‫הגדרת‬
.class ‫ בדומה לאופן השימוש במילה השמורה‬struct ‫( יש להשתמש במילה השמורה‬class ‫ )במקום‬struct ‫כדי להגדיר‬
:class-‫ ל‬struct ‫להלן ההבדלים העיקריים בין‬
.references types ‫ הם‬class values-‫ הרי ש‬value types ‫ הם‬struct values-‫ בעוד ש‬.1
.‫ אשר יורש מאחר‬struct ‫ לא ניתן להגדיר‬.2
.‫ שאנחנו לא יכולים להחליף באחר‬default constructor ‫ שאנו מגדירים יש‬struct-‫ ב‬3
:struct ‫להלן דוגמה להגדרה של‬
using System;
namespace abelski.csharp
{
class ConstructorsThisDemo
{
static void Main()
{
Rectangle rec = new Rectangle(14,12);
rec.PrintDetails();
}
}
struct Rectangle
{
private double width,height;
public Rectangle(double widthVal, double heightVal)
{
width = widthVal;
height = heightVal;
}
public void PrintDetails()
{
Console.WriteLine("["+width+","+height+"]");
}
}
}
© 2009 Haim Michael
‫‪21‬‬
‫להלן הפלט שנקבל‪.‬‬
‫‪© 2009 Haim Michael‬‬
22
partial ‫הגדרת מחלקה מסוג‬
partial ‫ את המילה השמורה‬.‫ ביותר מקובץ קוד מקור אחד‬interface ‫ או‬struct ‫ או‬class ‫ ניתן להגדיר‬partial ‫באמצעות‬
.‫ להלן דוגמה שממחישה זאת‬.(‫ )בהתאם למה שמגדירים‬interface ‫ או‬class, struct ‫יש למקם לפני המילה השמורה‬
using System;
namespace abelski.csharp
{
class ConstructorsThisDemo
{
static void Main()
{
Rectangle rec = new Rectangle(14,12);
rec.PrintDetails();
}
}
partial struct Rectangle
{
private double width,height;
public Rectangle(double widthVal, double heightVal)
{
width = widthVal;
height = heightVal;
}
}
}
:‫ובקובץ נפרד‬
using System;
namespace abelski.csharp
{
partial struct Rectangle
{
public void PrintDetails()
{
Console.WriteLine("["+width+","+height+"]");
}
}
}
© 2009 Haim Michael
‫‪23‬‬
‫להלן הפלט של התכנית‪.‬‬
‫‪© 2009 Haim Michael‬‬
24
‫הגדרת מחלקה סטטית‬
‫כאשר המחלקה שאנו מגדירים לא כוללת דבר מלבד מתודות סטטיות ומשתנים סטטיים אז ניתן להגדירה כמחלקה‬
static ‫ כדי להפוך מחלקה למחלקה סטטית יש להוסיף את המילה‬.‫ ממחלקה סטטית לא ניתן לייצור אובייקט‬.‫סטטית‬
.‫ הדוגמה הבאה מציגה זאת‬.‫לשורת הכותרת שלה‬
using System;
namespace abelski.csharp
{
class ConstructorsThisDemo
{
static void Main()
{
double num1 = 12.4;
double num2 = 14.6;
double total;
total = Utils.add(num1,num2);
Console.WriteLine("total="+total);
}
}
static class Utils
{
public static double add(double numA, double numB)
{
return numA+numB;
}
public static double subtract(double numA, double numB)
{
return numA-numB;
}
}
}
© 2009 Haim Michael
‫‪25‬‬
‫הפלט שנקבל הוא‪:‬‬
‫‪© 2009 Haim Michael‬‬
26
Object ‫המחלקה‬
:‫ מחלקה זו כוללת את המתודות החשובות הבאות‬.Object ‫כל מחלקה יורשת )ישירות או בעקיפין( מהמחלקה‬
ToString()
GetHashCode()
Equals()
Finalize()
GetType()
MemberWiseClone()
© 2009 Haim Michael