CodeGym /בלוג Java /Random-HE /מגבירים וקובעים
John Squirrels
רָמָה
San Francisco

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

פורסם בקבוצה
שלום! בהרצאות קודמות, כבר למדת כיצד להכריז על שיעורים מלאים משלך עם שיטות ותחומים. בשיעור של היום, נדבר על Getters ו-Setters בג'אווה. זו התקדמות רצינית, כל הכבוד! אבל עכשיו אני חייב לומר לך אמת לא נעימה. לא הצהרנו נכון על השיעורים שלנו! למה? ממבט ראשון, בכיתה הבאה אין טעויות:
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!");
   }
}
אבל כן. תאר לעצמך שאתה יושב בעבודה וכתוב את שיעור החתול הזה כדי לייצג חתולים. ואז אתה הולך הביתה. בזמן שאתה אינך, מתכנת אחר מגיע לעבודה. הוא יוצר את הכיתה הראשית שלו , שם הוא מתחיל להשתמש בכיתה החתול שכתבת.
public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
זה לא משנה למה הוא עשה את זה ואיך זה קרה (אולי הבחור עייף או לא ישן מספיק). משהו אחר חשוב: מחלקת החתול הנוכחית שלנו מאפשרת להקצות לשדות ערכים מטורפים לחלוטין. כתוצאה מכך, לתוכנית יש אובייקטים עם מצב לא חוקי (כגון חתול זה בן -1000 שנים). אז איזו שגיאה עשינו כשהכרזנו על המעמד שלנו? חשפנו את הנתונים של הכיתה שלנו. שדות השם, הגיל והמשקל הם ציבוריים. ניתן לגשת אליהם מכל מקום בתוכנה: פשוט צור אובייקט Cat ולכל מתכנת יש גישה ישירה לנתונים שלו דרך אופרטור הנקודה ( . )
Cat cat = new Cat();
cat.name = "";
כאן אנו ניגשים ישירות לשדה השם וקובעים את ערכו. אנחנו צריכים איכשהו להגן על הנתונים שלנו מפני הפרעות חיצוניות לא ראויות. מה אנחנו צריכים לעשות את זה? ראשית, יש לסמן את כל משתני המופע (שדות) עם השינוי הפרטי. פרטי הוא משנה הגישה המחמיר ביותר ב-Java. ברגע שתעשה זאת, השדות של מחלקת החתול לא יהיו נגישים מחוץ לכיתה.
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 Cat class's name field is private!
   }
}
המהדר רואה זאת ומיד מייצר שגיאה. עכשיו השדות מוגנים. אבל מסתבר שסגרנו את הגישה אולי חזק מדי: אתה לא יכול לקבל משקל של חתול קיים בתוכנית, גם אם אתה צריך. גם זו לא אופציה. כפי שהוא, הכיתה שלנו היא בעצם בלתי שמישה. באופן אידיאלי, עלינו לאפשר איזושהי גישה מוגבלת:
  • מתכנתים אחרים צריכים להיות מסוגלים ליצור אובייקטים של Cat
  • הם צריכים להיות מסוגלים לקרוא נתונים מחפצים קיימים (לדוגמה, לקבל את השם או הגיל של חתול קיים)
  • זה אמור להיות אפשרי גם להקצות ערכי שדות. אך בכך, יש לאפשר רק ערכים חוקיים. יש להגן על האובייקטים שלנו מפני ערכים לא חוקיים (למשל גיל = -1000 וכו').
זו רשימה הגונה של דרישות! במציאות, כל זה מושג בקלות בשיטות מיוחדות הנקראות גטרים ו-seters.
מגבירים וקובעים - 2
שמות אלו באים מ-"get" (כלומר "שיטה לקבל את הערך של שדה") ו-"set" (כלומר "שיטה לקביעת הערך של שדה"). בואו נראה איך הם נראים במחלקת החתול שלנו :
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;
   }
}
כפי שאתה יכול לראות, הם נראים די פשוטים :) השמות שלהם מורכבים לרוב מ"קבל"/"סט" בתוספת השם של השדה הרלוונטי. לדוגמה, השיטה getWeight() מחזירה את הערך של שדה המשקל עבור האובייקט עליו הוא נקרא. כך זה נראה בתוכנית:
public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);
       String smudgeName = smudge.getName();
       int smudgeAge = smudge.getAge();
       int smudgeWeight = smudge.getWeight();

       System.out.println("Cat's name: " + smudgeName);
       System.out.println("Cat's age: " + smudgeAge);
       System.out.println("Cat's weight: " + smudgeWeight);
   }
}
פלט מסוף:
Cat's name: Smudge
Cat's age: 5
Cat's weight: 4
כעת מחלקה אחרת ( Main ) יכולה לגשת לשדות החתולים , אבל רק דרך מגברים. שימו לב שלגטרים יש את שינוי הגישה הציבורי, כלומר הם זמינים מכל מקום בתוכנית. אבל מה לגבי הקצאת ערכים? לשם כך נועדו שיטות מגדיר
public void setName(String name) {
   this.name = name;
}
כפי שאתה יכול לראות, הם גם פשוטים. אנו קוראים למתודה setName() באובייקט Cat , מעבירים מחרוזת כארגומנט, והמחרוזת מוקצית לשדה השם של האובייקט.
public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);

       System.out.println("Cat's original name: " + smudge.getName());
       smudge.setName("Mr. Smudge");
       System.out.println("Cat's new name: " + smudge.getName());
   }
}
כאן אנו משתמשים גם בגטרים וגם בסטרים. ראשית, אנו משתמשים ב-getter כדי לקבל ולהציג את שמו המקורי של החתול. לאחר מכן, אנו משתמשים במגדיר כדי להקצות שם חדש ("מר סמודג'"). ואז אנחנו משתמשים שוב ב-getter כדי לקבל את השם (כדי לבדוק אם הוא באמת השתנה). פלט מסוף:
Cat's original name: Smudge
Cat's new name: Mr. Smudge
אז מה ההבדל? אנחנו עדיין יכולים להקצות ערכים לא חוקיים לשדות גם אם יש לנו מגדירים:
public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);
       smudge.setAge(-1000);

       System.out.println("Smudge's age: " + smudge.getAge());
   }
}
פלט מסוף:
Smudge's age: -1000 years
ההבדל הוא ששיטה היא שיטה מן המניין. ובניגוד לשדה, שיטה מאפשרת לך לכתוב את לוגיקת האימות הדרושה כדי למנוע ערכים בלתי מקובלים. לדוגמה, אתה יכול בקלות למנוע הקצאת מספר שלילי כגיל:
public void setAge(int age) {
   if (age >= 0) {
       this.age = age;
   } else {
       System.out.println("Error! Age can't be negative!");
   }
}
ועכשיו הקוד שלנו עובד כמו שצריך!
public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);
       smudge.setAge(-1000);

       System.out.println("Smudge's age: " + smudge.getAge());
   }
}
פלט מסוף:
Error! Age can't be negative!
Smudge's age: 5 years
בתוך המגדיר יצרנו הגבלה שהגנה עלינו מפני הניסיון להגדיר נתונים לא חוקיים. הגיל של סמודג' לא השתנה. אתה תמיד צריך ליצור קבלים ומקבעים. גם אם אין הגבלות על הערכים שהשדות שלך יכולים לקבל, שיטות עוזרות אלו לא יזיקו. תאר לעצמך את המצב הבא: אתה והקולגות שלך כותבים תוכנית ביחד. אתה יוצר כיתת חתול עם שדות ציבוריים. כל המתכנתים משתמשים בהם איך שהם רוצים. ואז יום בהיר אחד אתה מבין: "חרא, במוקדם או במאוחר מישהו עלול להקצות בטעות מספר שלילי למשקל! אנחנו צריכים ליצור קובעים ולהפוך את כל השדות לפרטיים!" אתה עושה בדיוק את זה, ושובר באופן מיידי את כל הקוד שנכתב על ידי עמיתיך. אחרי הכל, הם כבר כתבו חבורה של קוד שניגש ישירות לשדות החתול .
cat.name = "Behemoth";
ועכשיו השדות פרטיים והמהדר פולט המון שגיאות!
cat.name = "Behemoth";//error! The Cat class's name field is private!
במקרה זה, עדיף להסתיר את השדות וליצור גטר ומגדיר כבר מההתחלה. כל הקולגות שלך היו משתמשים בהם. ואם הבנת באיחור שאתה צריך להגביל איכשהו את ערכי השדות, יכולת פשוט לרשום את הצ'ק בתוך ה-Setter. והקוד של אף אחד לא יישבר. כמובן, אם אתה רוצה שהגישה לשדה תהיה רק ​​"לקריאה בלבד", אתה יכול ליצור רק מגבר עבורו. רק שיטות צריכות להיות זמינות חיצונית (כלומר מחוץ לכיתה שלך). יש להסתיר נתונים. נוכל לעשות השוואה לטלפון נייד. תארו לעצמכם שבמקום הטלפון הסלולרי הסגור הרגיל, קיבלת טלפון עם נרתיק פתוח, עם כל מיני חוטים בולטים, מעגלים וכו'. אבל הטלפון עובד: אם תנסה מאוד ותדחוף את המעגלים, אולי אפילו תהיה מסוגל לבצע שיחה. אבל אתה כנראה פשוט תשבור את זה.
מגבירים וקובעים - 3
במקום זאת, היצרן נותן לך ממשק: המשתמש פשוט מזין את הספרות הנכונות, לוחץ על כפתור השיחה הירוק והשיחה מתחילה. לא אכפת לה מה קורה בפנים עם המעגלים והחוטים, או איך הם יעשו את העבודה שלהם. בדוגמה זו, החברה מגבילה את הגישה ל"פנים" (נתונים) של הטלפון וחושפת רק ממשק (שיטות). כתוצאה מכך, המשתמש מקבל את מה שהיא רצתה (היכולת לבצע שיחה) ובוודאי לא ישבור שום דבר בפנים. כדי לחזק את מה שלמדת, אנו מציעים לך לצפות בשיעור וידאו מקורס Java שלנו
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION