JavaRush /בלוג Java /Random-HE /משנה גישה. פרטי, מוגן, ברירת מחדל, ציבורי

משנה גישה. פרטי, מוגן, ברירת מחדל, ציבורי

פורסם בקבוצה
שלום! בהרצאה של היום נכיר את המושג " משתני גישה " ונראה דוגמאות לעבודה איתם. משנה גישה.  פרטי, מוגן, ברירת מחדל, ציבורי - 1למרות שהמילה "בואו להכיר" לא תהיה לגמרי נכונה: את רובם אתם כבר מכירים מהרצאות קודמות. ליתר בטחון, בואו נרענן את הזיכרון לגבי העיקר. משנה גישה הם לרוב מילות מפתח המווסתות את רמת הגישה לחלקים שונים של הקוד שלך. למה "לרוב"? מכיוון שאחד מהם מוגדר כברירת מחדל ואינו מסומן על ידי מילת מפתח :) יש בסך הכל ארבעה מגדי גישה בג'אווה. אנו מפרטים אותם בסדר מהמחמיר ביותר ל"רך" ביותר:
  • פְּרָטִי;
  • מוּגָן;
  • ברירת מחדל (חבילה גלויה);
  • פּוּמְבֵּי
בואו נסתכל על כל אחד מהם, נחליט מתי הם יכולים להועיל לנו וניתן דוגמאות :)

שינוי פרטי

משנה גישה.  פרטי, מוגן, ברירת מחדל, ציבורי - 2Private- משנה הגישה המגביל ביותר. זה מגביל את הנראות של נתונים ושיטות בתוך מחלקה אחת. אתה מכיר את השינוי הזה מההרצאה על גטרים ומגדירים. זוכרים את הדוגמה הזו?
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 שנים, שם "" ומשקל של 0. כדי לפתור בעיה זו, אנו השתמשו ב-getters ו-seters , וגם גישה מוגבלת לנתונים באמצעות משנה private.
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) {
       // checking the input parameter
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       // checking the input parameter
       this.age = age;
   }

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       // checking the input parameter
       this.weight = weight;
   }
}
למעשה, הגבלת הגישה לשדות והטמעת מגדירים-מגדירים היא הדוגמה הנפוצה ביותר לשימוש privateבעבודה אמיתית. כלומר, הטמעת אנקפסולציה בתוכנית היא המטרה העיקרית של השינוי הזה. זה חל לא רק על שדות, אגב. תאר לעצמך שבתוכנית שלך יש שיטה המיישמת פונקציונליות מורכבת מאוד. כדי להמציא את זה כדוגמה... נניח שהשיטה שלך readDataFromCollider()לוקחת כתובת עם נתונים כקלט, קוראת נתונים ממאיץ האדרון הגדול בפורמט בתים, ממירה את הנתונים האלה לטקסט, כותבת אותם לקובץ ומדפיסה אותם. אפילו תיאור השיטה נראה מצמרר, שלא לדבר על הקוד :) כדי להגביר את קריאות הקוד, כדאי לא לכתוב את ההיגיון המורכב של השיטה במקום אחד, אלא להיפך, לשבור את הפונקציונליות לשיטות נפרדות. לדוגמה, השיטה readByteData()אחראית על קריאת נתונים, convertBytesToSymbols()המרת הנתונים שנקראו מהמאיץ לטקסט, saveToFile()שמירת הטקסט שנוצר לקובץ והדפסת printColliderData()קובץ הנתונים שלנו. השיטה readDataFromCollider()תהיה בסופו של דבר הרבה יותר פשוטה:
public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   public byte[] readByteData(Path pathToData) {

       // reads data in bytes
   }

   public String[] convertBytesToSymbols(byte[] colliderDataInBytes) {

       // convert bytes to characters
   }

   public File saveToFile(String[] colliderData) {

       // save the read data to a file
   }

   public void printColliderData(File fileWithColliderData) {

       // print data from file
   }
}
עם זאת, כזכור מההרצאה על ממשקים, המשתמש מקבל רק גישה לממשק הסופי. וארבע השיטות שלנו אינן חלק מזה. הם עזר : יצרנו אותם כדי לשפר את קריאות הקוד וכדי להימנע מדחיסת ארבע משימות שונות בשיטה אחת. אין צורך לתת למשתמש גישה לשיטות אלו. אם למשתמש יש גישה לשיטה בעת עבודה עם מתנגש convertBytesToSymbols(), סביר להניח שהוא פשוט לא יבין מהי שיטה זו ולמה היא נחוצה. אילו בתים מומרים? מאיפה הם באו? למה להמיר אותם לטקסט? ההיגיון שפועל בשיטה זו אינו חלק מממשק המשתמש. רק השיטה readDataFromCollider()היא חלק מהממשק. מה לעשות עם ארבע השיטות ה"פנימיות" הללו? ימין! הגבל את הגישה אליהם באמצעות משנה private. כך הם יכולים בקלות לעשות את עבודתם בתוך הכיתה ולא לבלבל את המשתמש, שלא צריך את ההיגיון של כל אחד מהם בנפרד.
public class ColliderUtil {

   public void readDataFromCollider(Path pathToData) {
       byte[] colliderData = readByteData(pathToData);
       String[] textData = convertBytesToSymbols(colliderData);
       File fileWithData = saveToFile(textData);
       printColliderData(fileWithData);
   }

   private byte[] readByteData(Path pathToData) {
       // reads data in bytes
   }

   private String[] convertBytesToSymbols(byte[] colliderDataInBytes) {
       // convert bytes to characters
   }

   private File saveToFile(String[] colliderData) {
       // save the read data to a file
   }

   private void printColliderData(File fileWithColliderData) {
       // print data from file
   }
}

השינוי מוגן

שינוי הגישה המגביל הבא ביותר הוא protected. משנה גישה.  פרטי, מוגן, ברירת מחדל, ציבורי - 3 שדות ושיטות המיועדים לשינוי הגישה protectedיהיו גלויים:
  • בתוך כל השיעורים שנמצאים באותה חבילה כמו שלנו;
  • בתוך כל השיעורים היורשים של הכיתה שלנו.
מיד קשה לדמיין מתי זה עשוי להיות נחוץ. אל תתפלאו: protectedיש הרבה פחות מקרים של יישום מאשר private, והם ספציפיים. תארו לעצמכם שיש לנו מחלקה מופשטת AbstractSecretAgentשמציינת סוכן חשאי של סוכנות ביון כלשהי, וכן חבילה top_secretהמכילה את המעמד הזה ואת צאצאיו. שיעורי בטון - FBISecretAgent, MI6SecretAgent, MossadSecretAgentוכו' - עוברים בירושה ממנו. בתוך המחלקה המופשטת אנחנו רוצים ליישם מונה סוכן. כאשר אובייקט סוכן חדש נוצר איפשהו בתוכנית, הוא יגדל.
package top_secret;

public abstract class AbstractSecretAgent {

   public static int agentCount = 0;
}
אבל הסוכנים שלנו סודיים! זה אומר שרק הם ואף אחד אחר לא צריכים לדעת על המספר שלהם. אנחנו יכולים בקלות להוסיף משנה protectedלשדה agentCount, ואז או אובייקטים של מחלקות סוכן חשאי אחרות, או מחלקות אלה שנמצאות בחבילה ה"סודית" שלנו, יכולים לקבל את הערך שלו top_secret.
public abstract class AbstractSecretAgent {

   protected static int agentCount = 0;
}
עבור משימות ספציפיות כל כך יש צורך בשינוי protected:)

שינוי גלוי של החבילה

הבא ברשימה שלנו הוא המשנה defaultאו, כפי שהוא נקרא גם, package visible. זה לא מצוין על ידי מילת מפתח מכיוון שהוא מוגדר כברירת מחדל ב-Java עבור כל השדות והשיטות. אם אתה כותב בקוד שלך -
int x = 10;
... למשתנה xתהיה אותה package visibleגישה. אם שיטה (או משתנה) לא מסומנת בשינוי כלשהו, ​​היא נחשבת מסומנת ב"שינוי ברירת המחדל". משתנים או שיטות עם משנה כזה (כלומר ללא כל) גלויים לכל המחלקות של החבילה שבה הם מוכרזים. ורק להם. השימושים בו מוגבלים, בדיוק כמו המשנה protected. לרוב, default-access משמש בחבילה שבה יש כמה מחלקות שירות שאינן מיישמות את הפונקציונליות של כל המחלקות האחרות בחבילה זו. בואו ניתן דוגמה. תאר לעצמך שיש לנו חבילת " שירותים ". בתוכו מחלקות שונות שעובדות עם בסיס הנתונים. למשל, יש מחלקה UserServiceשקוראת נתוני משתמש ממסד נתונים, מחלקה CarServiceשקוראת נתונים על מכוניות מאותו מסד נתונים ועוד מחלקות, שכל אחת מהן עובדת עם סוג אובייקטים משלה וקוראת נתונים עליהם ממסד הנתונים.
package services;

public class UserService {
}

package services;

public class CarService {
}
עם זאת, מצב יכול לקרות בקלות כאשר הנתונים במסד הנתונים נמצאים בפורמט אחד, אך אנו זקוקים להם בפורמט אחר. תארו לעצמכם שתאריך הלידה של המשתמש במסד הנתונים מאוחסן בפורמט TIMESTAMP WITH TIME ZONE...
2014-04-04 20:32:59.390583+02
...אנחנו צריכים במקום זאת את האובייקט הפשוט ביותר - java.util.Date. לשם כך, נוכל ליצור servicesמחלקה מיוחדת בתוך החבילה Mapper. הוא יהיה אחראי להמרת נתונים ממסד הנתונים לאובייקטי Java המוכרים לנו. כיתת עוזרים פשוטה. בדרך כלל אנו יוצרים את כל המחלקות כ- public class ClassName, אבל זה לא הכרחי. אנחנו יכולים להכריז על כיתת העוזרים שלנו פשוט כ- class Mapper. במקרה זה, הוא עדיין עושה את עבודתו, אך אינו גלוי לאף אחד מחוץ לחבילה services!
package services;

class Mapper {
}


package services;

public class CarService {

   Mapper mapper;
}
וזה, למעשה, ההיגיון הנכון: למה שמישהו מחוץ לחבילה יראה מחלקה עזר שעובדת רק עם מחלקות של אותה חבילה?

שינוי ציבורי

ואחרון ברשימה, אבל לא פחות חשוב - המשנה public! פגשת אותו ביום הראשון של הלימודים ב-JavaRush, והשקת public static void main(String[] args). משנה גישה.  פרטי, מוגן, ברירת מחדל, ציבורי - 4 כעת, לאחר שלמדת את ההרצאות על ממשקים, מטרתה ברורה לך :) הרי publicהיא נוצרה על מנת לתת משהו למשתמשים. לדוגמה, הממשק של התוכנית שלך. נניח שכתבת תוכנית מתרגם, והיא יכולה לתרגם טקסט רוסי לאנגלית. יצרת שיטה translate(String textInRussian)שבתוכה מיושמת ההיגיון הדרוש. סימנתם שיטה זו במילה public, ועכשיו היא תהפוך לחלק מהממשק:
public class Translator {

   public String translate(String textInRussian) {

       // translates text from Russian to English
   }
}
אתה יכול לשייך שיחה לשיטה זו עם כפתור "תרגם" במסך התוכנית - וזהו! כל אחד יכול להשתמש בו. חלקים מהקוד המסומנים במשנה publicמיועדים למשתמש הקצה. כדי לתת דוגמה מהחיים, privateאלו כל התהליכים המתרחשים בתוך הטלוויזיה כשהיא פועלת, ואלו publicהכפתורים בשלט הטלוויזיה בעזרתם יכול המשתמש לשלוט בה. יחד עם זאת, הוא לא צריך לדעת איך הטלוויזיה עובדת ואיך היא פועלת. השלט הרחוק הוא סט publicשל שיטות: on(), off(), , , וכו' nextChannel().previousChannel()increaseVolume()decreaseVolume()
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION