JavaRush /בלוג Java /Random-HE /מגבירים וקובעים

מגבירים וקובעים

פורסם בקבוצה
שלום! בהרצאות קודמות כבר למדת איך ליצור שיעורים משלך, עם תחומים ושיטות. זו התקדמות רצינית, כל הכבוד! אבל עכשיו אני חייב לומר לך אמת לא נעימה. לא יצרנו את השיעורים שלנו כמו שצריך! למה? במבט ראשון, אין שגיאות במחלקה זו:
public class Cat {

   public String name;
   public int age;
   public int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }
}
למעשה, יש. תאר לעצמך שבזמן שאתה יושב בעבודה כתבת שיעור כזה Cat, שמציין חתולים. והוא הלך הביתה. בזמן שלא היית, מתכנת אחר הגיע לעבודה, יצר מחלקה משלו Main, שם הוא התחיל להשתמש בכיתה שכתבת Cat.
public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
זה לא משנה למה הוא עשה את זה או איך זה קרה: אולי האדם היה עייף או לא ישן מספיק. דבר נוסף חשוב: הכיתה הנוכחית שלנו Catמאפשרת לך להקצות ערכים מטורפים לשדות. כתוצאה מכך, התוכנית מכילה אובייקטים עם מצב שגוי, כמו חתול זה עם גיל של -1000 שנים. איזו טעות עשינו בסופו של דבר? כשיצרנו את המחלקה, חשפנו את הנתונים שלה. שדות name, ageוהם weightבנחלת הכלל. ניתן לגשת אליהם בכל מקום בתוכנית: פשוט צור אובייקט Cat- וזהו, לכל מתכנת יש גישה לנתונים שלו ישירות דרך האופרטור " ."
Cat cat = new Cat();
cat.name = "";
כאן אנו ניגשים ישירות לשדה nameוקובעים את ערכו. אנחנו צריכים איכשהו להגן על הנתונים שלנו מפני הפרעות חיצוניות שגויות. מה צריך בשביל זה? ראשית, יש לסמן את כל משתני המופע (שדות) במשנה private. פרטי הוא משנה הגישה המחמיר ביותר ב-Java. אם אתה משתמש בו, שדות הכיתה Catלא יהיו נגישים מחוצה לה.
public class Cat {

   private String name;
   private int age;
   private int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";//error! The name field in the Cat class has private access!
   }
}
המהדר רואה זאת ומיד מייצר שגיאה. כעת נראה שהשדות מוגנים. אבל מסתבר שהגישה אליהם סגורה "באופן חזק": התוכנית לא יכולה אפילו לקבל משקל של חתול קיים, אם יש צורך בכך. זו גם לא אופציה: בצורה זו הכיתה שלנו כמעט בלתי אפשרית לשימוש. באופן אידיאלי אנחנו צריכים לאפשר איזושהי גישה מוגבלת לנתונים:
  • מתכנתים אחרים צריכים להיות מסוגלים ליצור אובייקטיםCat
  • הם צריכים להיות מסוגלים לקרוא נתונים מאובייקטים שכבר קיימים (לדוגמה, לקבל את השם או הגיל של חתול שכבר קיים)
  • זה אמור להיות אפשרי גם להקצות ערכי שדות. אבל יחד עם זאת - רק ערכים נכונים. יש להגן על החפצים שלנו מפני חפצים לא נכונים (ללא "גיל = -1000 שנים" וכדומה).
רשימת הדרישות הגונה! אבל למעשה, כל זה מושג בקלות באמצעות שיטות מיוחדות - גטרים וקובעים .
מגבירים וקובעים - 2
השם בא מהאנגלית " get " - " receive " (כלומר, "שיטה לקבלת ערך של שדה") ו- set - " set " (כלומר, "שיטה לקביעת ערך של שדה"). בוא נראה איך הם נראים תוך שימוש בכיתה שלנו כדוגמה Cat:
public class Cat {

   private String name;
   private int age;
   private int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       this.age = age;
   }

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       this.weight = weight;
   }
}
כפי שניתן לראות, הכל די פשוט :) השמות שלהם מורכבים לרוב מהמילה get/set + שם השדה שעליו הם אחראים. לדוגמה, שיטה getWeight()מחזירה את הערך של שדה weightעבור האובייקט שעבורו נקראה. כך זה נראה בתוכנית:
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);
       String barsikName = barsik.getName();
       int barsikAge = barsik.getAge();
       int barsikWeight = barsik.getWeight();

       System.out.println("Cat name: " + barsikName);
       System.out.println("Cat's age: " + barsikAge);
       System.out.println("Weight of the cat: " + barsikWeight);
   }
}
פלט מסוף:

Name кота: Барсик
Возраст кота: 5
Вес кота: 4
עכשיו ממחלקה אחרת ( Main) יש גישה לשדות Cat, אבל רק דרך getters . שים לב של-Gutters יש משנה גישה public, כלומר הם נגישים מכל מקום בתוכנית. מה לגבי הקצאת ערכים? שיטות קבע אחראיות לכך
public void setName(String name) {
   this.name = name;
}
העבודה שלהם, כפי שאתה יכול לראות, היא גם פשוטה. אנו קוראים למתודה setName()על אובייקט Cat, מעבירים לה מחרוזת כארגומנט, והמחרוזת הזו מוקצית לשדה nameשל האובייקט שלנו.
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);

       System.out.println("The original name of the cat is " + barsik.getName());
       barsik.setName("Basil");
       System.out.println("The new name of the cat -" + barsik.getName());
   }
}
כאן השתמשנו גם בגטרים וגם בסטרים. ראשית, באמצעות גטר, קיבלנו והצגנו את השם הראשוני של החתול בקונסולה. לאחר מכן, באמצעות מגדיר, nameהוקצה ערך חדש לשדה שלו - "Vasily". ולאחר מכן, באמצעות גטר, קיבלנו את השם שוב כדי לבדוק אם הוא באמת השתנה. פלט מסוף:

Изначальное Name кота — Барсик
Новое Name кота — Васorй
נראה, מה ההבדל? אנו יכולים גם להקצות ערכים שגויים לשדות אובייקט, גם אם יש לנו מגדירים:
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);
       barsik.setAge(-1000);

       System.out.println("Age of Barsik -" + barsik.getAge() + " years");
   }
}
פלט מסוף:

Возраст Барсика — -1000 лет
ההבדל הוא ששיטה היא שיטה מן המניין . ובשיטה, בניגוד לשדה, אתה יכול לשים את היגיון האימות שאתה צריך כדי למנוע ערכים לא מקובלים. לדוגמה, אתה יכול בקלות להשבית הקצאת מספר שלילי כגיל:
public void setAge(int age) {
   if (age >= 0) {
       this.age = age;
   } else {
       System.out.println("Error! Age cannot be negative!");
   }
}
ועכשיו הקוד שלנו עובד כמו שצריך!
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);
       barsik.setAge(-1000);

       System.out.println("Age of Barsik -" + barsik.getAge() + " years");
   }
}
פלט מסוף:

Ошибка! Возраст не может быть отрицательным числом!
Возраст Барсика — 5 лет
ישנה הגבלה בתוך המגדיר, והיא מגינה מפני ניסיונות להגדיר נתונים שגויים. גילו של ברסיק נותר ללא שינוי. תמיד צריך ליצור מגבירים וקובעים. גם אם לשדות שלך אין הגבלות על ערכים אפשריים, לא ייגרם מהם נזק. תארו לעצמכם מצב: אתה והקולגות שלך כותבים תוכנית ביחד. יצרת מחלקה Catעם שדות ציבוריים, וכל המתכנתים משתמשים בהם כרצונם. ואז יום בהיר אחד מתברר לך: "לעזאזל, במוקדם או במאוחר מישהו עלול להקצות בטעות מספר שלילי למשתנה weight! אנחנו צריכים ליצור מגדירים ולהפוך את כל השדות לפרטיים!" אתה יוצר אותם, וכל הקוד שנכתב על ידי עמיתיך נשבר מיידית. אחרי הכל, הם כבר כתבו צרור קוד שבו הם ניגשו Catישירות לשדות.
cat.name = "Hippopotamus";
ועכשיו השדות הפכו לפרטיים והמהדר מייצר חבורה של שגיאות!
cat.name = "Hippopotamus";//error! The name field of the Cat class has private access!
במצב כזה, עדיף להסתיר את השדות וליצור מגדירים כבר מההתחלה . כל הקולגות שלך היו משתמשים בהם, ואם יתברר לך מאוחר שאתה צריך להגביל את ערכי השדות, פשוט תוסיף צ'ק בתוך הקובע. ואף אחד לא ישבור את הקוד שכבר נכתב. כמובן, אם אתה רוצה גישה לקריאה בלבד לשדה מסוים, אתה יכול ליצור עבורו משבר אחד. "בחוץ", כלומר מחוץ לכיתה שלך, רק שיטות צריכות להיות נגישות. הנתונים חייבים להיות מוסתרים.
מגבירים וקובעים - 4
ניתן ליצור אנלוגיה עם טלפון נייד. תאר לעצמך שבמקום טלפון נייד רגיל מופעל, קיבלת טלפון עם נרתיק פתוח, שבו נמצאים כל החוטים, המעגלים וכו'. בולט. הטלפון עובד: אם תנסה להתעסק בתרשימים, אולי אפילו תוכל להתקשר. אבל כנראה שפשוט תשבור את זה. במקום זאת, החברה היצרנית נותנת לך ממשק: הלקוח פשוט מחייג את המספרים הנדרשים, לוחץ על הכפתור הירוק עם השפופרת, והשיחה מתחילה. ולא אכפת לו מה קורה בפנים עם המעגלים והחוטים ואיך הם מבצעים את המשימה שלהם. בדוגמה זו, לחברה יש גישה מוגבלת ל"פנימיים" (נתונים) של הטלפון והשאירה רק את הממשק (השיטות) בחוץ. כתוצאה מכך, הלקוח יקבל את מבוקשו (תתקשר) ובהחלט לא ישבור שום דבר בפנים.
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION