אובייקטים ו-OOP
מהו אובייקט?
אובייקט (object) הוא מופע של מחלקה. המחלקה היא התבנית, האובייקט הוא "דבר" קונקרטי שנוצר לפי התבנית.
אנלוגיה: מחלקה = תוכנית אדריכלית של בית. אובייקט = הבית שבנו בפועל. תוכנית אחת - הרבה בתים.
תכנות מונחה עצמים (OOP)
Object-Oriented Programming הוא גישה לתכנות שבה מארגנים את הקוד סביב "אובייקטים" - ישויות עם: - מצב (state) - נתונים שהם שומרים - התנהגות (behavior) - פעולות שאפשר לעשות עליהם
Java היא שפה שבעצם המהות שלה היא מונחית עצמים - הכל סובב סביב מחלקות ואובייקטים.
דוגמה פשוטה
public class Person {
// שדות (מצב)
String name;
int age;
// מתודות (התנהגות)
public void greet() {
System.out.println("שלום, אני " + name);
}
}
יצירה ושימוש
public class Main {
public static void main(String[] args) {
Person p = new Person();
p.name = "דוד";
p.age = 30;
p.greet(); // "שלום, אני דוד"
}
}
בנאי (Constructor)
בנאי הוא מתודה מיוחדת שרצה ברגע יצירת האובייקט. שמה זהה לשם המחלקה, ואין לה טיפוס חזרה.
public class Person {
String name;
int age;
// בנאי
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void greet() {
System.out.println("שלום, אני " + name);
}
}
שימוש
Person p1 = new Person("דוד", 30);
Person p2 = new Person("רחל", 25);
p1.greet();
p2.greet();
this
this היא הפנייה לאובייקט הנוכחי. שימושי כשיש התנגשות שמות בין פרמטר לשדה:
public Person(String name, int age) {
this.name = name; // this.name = השדה, name = הפרמטר
this.age = age;
}
בנאי ברירת מחדל
אם לא מגדירים בנאי - Java יוצרת בנאי ריק בעצמה:
public class Dog {
String name;
// אין בנאי מוגדר - Java יוצרת: public Dog() {}
}
Dog d = new Dog(); // עובד
אבל אם מגדירים בנאי - הברירת מחדל נעלמת:
public class Dog {
String name;
public Dog(String name) {
this.name = name;
}
}
Dog d = new Dog(); // שגיאה!
Dog d2 = new Dog("רקסי"); // עובד
הסתרה (Encapsulation)
עיקרון יסוד ב-OOP: לא לחשוף את המצב הפנימי של אובייקט ישירות. במקום זה - לעבוד דרך מתודות ציבוריות.
שלא כמו שצריך
public class BankAccount {
public double balance;
}
BankAccount acc = new BankAccount();
acc.balance = -1000; // בעיה! אפשר להגדיר כל ערך
כמו שצריך
public class BankAccount {
private double balance;
public double getBalance() {
return balance;
}
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
}
}
}
מילות מפתח לנגישות
| מילת מפתח | משמעות |
|---|---|
public |
נגיש מכל מקום |
private |
נגיש רק מתוך המחלקה |
protected |
נגיש למחלקה, לתת-מחלקות, ולאותה חבילה |
| (ללא) | נגיש לאותה חבילה (package-private) |
Getters ו-Setters
דפוס סטנדרטי לחשיפה בטוחה של שדות:
public class Person {
private String name;
private int age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) {
if (age >= 0) {
this.age = age;
}
}
}
ארבעת עקרונות ה-OOP
1. Encapsulation - הסתרה
הסתרת הפרטים הפנימיים, חשיפה רק של מה שצריך.
2. Inheritance - ירושה
מחלקה יכולה "לרשת" ממחלקה אחרת, ולהרחיב אותה:
public class Animal {
String name;
public void eat() { System.out.println("אוכל..."); }
}
public class Dog extends Animal {
public void bark() { System.out.println("הב הב!"); }
}
Dog d = new Dog();
d.eat(); // יורש מ-Animal
d.bark(); // משלו
3. Polymorphism - פולימורפיזם
אותה פעולה יכולה להתנהג שונה באובייקטים שונים.
public class Animal {
public void sound() { System.out.println("רעש כללי"); }
}
public class Dog extends Animal {
@Override
public void sound() { System.out.println("הב הב!"); }
}
public class Cat extends Animal {
@Override
public void sound() { System.out.println("מיאו!"); }
}
Animal a = new Dog();
a.sound(); // "הב הב!" - לא "רעש כללי"!
4. Abstraction - הפשטה
עבודה עם רעיונות מופשטים, לא עם פרטי היישום.
static מול non-static
- static - שייך למחלקה עצמה. משותף לכל האובייקטים.
- non-static - שייך לכל אובייקט בנפרד.
public class Counter {
static int total = 0; // משותף
int mine = 0; // אישי
public Counter() {
total++;
mine++;
}
}
Counter c1 = new Counter(); // total=1, c1.mine=1
Counter c2 = new Counter(); // total=2, c2.mine=1, c1.mine=1
toString, equals, hashCode
מתודות ש-Java ממליצה לממש במחלקות שלכם:
toString
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
שימוש: System.out.println(person) יקרא אוטומטית ל-toString().
equals
להגדיר "שוויון" בין שני אובייקטים:
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Person)) return false;
Person other = (Person) obj;
return this.age == other.age && this.name.equals(other.name);
}
דוגמה מלאה
public class Student {
private String name;
private int grade;
public Student(String name, int grade) {
this.name = name;
this.grade = grade;
}
public String getName() { return name; }
public int getGrade() { return grade; }
public boolean passed() {
return grade >= 60;
}
@Override
public String toString() {
return name + " (" + grade + ")";
}
}
public class Main {
public static void main(String[] args) {
Student s1 = new Student("דוד", 85);
Student s2 = new Student("רחל", 45);
System.out.println(s1); // דוד (85)
System.out.println(s1.passed()); // true
System.out.println(s2.passed()); // false
}
}
בדקו את עצמכם
נסו לענות לבד לפני שאתם פותחים את התשובה.
-
מה תפקיד הבנאי (constructor)?
הצגת התשובה
תשובה ג. הבנאי רץ עם new וממלא את השדות ההתחלתיים.
-
למה מגדירים שדות כ-
privateעם getters ו-setters?הצגת התשובה
תשובה ד. הכמסה מונעת שינוי לא חוקי מבחוץ, למשל גיל שלילי.
-
מה מחזירה
thisבתוך מתודה?הצגת התשובה
תשובה ב. this מפנה לאובייקט שעליו המתודה הופעלה.