فئة الصديق

يمكن لفئة الصديق أو العائلة في ++c الوصول إلى الأعضاء الخاصة والمحمية للفئة التي أُعلنت  فيها كصديق أو كعائلة.  أحد الاستخدامات المهمة لفئة هذا الكود هو أن يكون جزء من بنية البيانات، الذي يتم تمثيله بواسطة فئة، قادرًا على الوصول إلى الفئة الرئيسية التي تمثل بنية البيانات تلك. تسمح آلية فئة هذا الكود بتوسيع مساحة التخزين إلى اجزاء، مع الاحتفاظ بالتغليف المناسب كما يراه مستخدمو بنية البيانات.

على غرار فئة الصديق، فإن وظيفة هذا الكود هي وظيفة تُمنح حق الوصول إلى الأعضاء الخاصة والمحمية للفئة التي أعلنت فيها كصديق أو شخص كالعائلة.

يوضح المثال التالي كيفية استخدام فئة الأصدقاء لهيكل بيانات الرسم المحدد، حيث يتم تمثيل الرسم المحدد من خلال الرسم المحدد من الدرجة الرئيسية، ويتم تمثيل قمصان الرسم من قبل الفئة:

#include <iostream>
#include <memory>
#include <string>
#include <unordered_set>

class Graph;

class Vertex {
 public:
  explicit Vertex(std::string name) : edges_(), name_(std::move(name)) {}

  auto begin() const { return edges_.cbegin(); }
  auto end() const { return edges_.cend(); }

  const auto& name() const { return name_; }

 private:
  // Vertex gives access-rights to Graph.
  friend class Graph;

  std::unordered_set<Vertex*> edges_;
  std::string name_;
};

class Graph {
 public:
  ~Graph() {
    while (!vertices_.empty()) {
      auto vertex = vertices_.begin();
      RemoveVertex(*vertex);
    }
  }

  auto AddVertex(const std::string& name) -> Vertex* {
    auto vertex = std::make_unique<Vertex>(name);
    auto iter = vertices_.insert(vertex.get());
    return vertex.release();
  }

  void RemoveVertex(Vertex* vertex) {
    vertices_.erase(vertex);
    delete vertex;
  }

  auto AddEdge(Vertex* from, Vertex* to) {
    // Graph can access Vertex's private fields because Vertex declared Graph as
    // a friend.
    from->edges_.insert(to);
  }

  auto begin() const { return vertices_.cbegin(); }
  auto end() const { return vertices_.cend(); }

 private:
  std::unordered_set<Vertex*> vertices_;
};

 التغليف 
يؤدي الاستخدام الصحيح لفئات الصديق أو العائلة إلى زيادة التغليف، لأنه يسمح بتوسيع الوصول الخاص لهيكل البيانات إلى أجزائه التي يمتلكها هيكل البيانات بدون السماح بالوصول الى اي فئة خارجية أخرى ليست تابعة لها. بهذه الطريقة تظل بنية البيانات محمية ضد المحاولات العرضية لكسر ثوابت بنية البيانات من الخارج.

من المهم ملاحظة أن الفئة لا يمكنها منح نفسها حق الوصول إلى جزء خاص بفئة أخرى ليست من نطاق فئتها؛ حيث سيؤدي ذلك إلى كسر التغليف، بل إن الفصل يمنح فصلًا آخرا إمكانية الوصول إلى أجزائه الخاصة عن طريق إعلان هذا الفصل كصديق أو عائلة. في مثال الرسم المحدد أدناه، لا يمكن للرسم البياني أن يعلن نفسه صديقًا لـ Vertex. بدلاً من ذلك، تعلن Vertex أن Graph صديق، وبالتالي توفر لـ Graph إمكانية الوصول لأماكنها الخاصة.

إن حقيقة أن فئة ما تختار أصدقائها تعني أن الصداقة أو العلاقة ليست متناظرة بشكل عام. في مثال الرسم المحدد، لا يمكن لـ Vertex الوصول لأماكنها الخاصة لفئة غيرها ك Graph، على الرغم من أن Graph يمكنه الوصول إلى الحقول الخاصة لـ Vertex.

 البدائل 
يتم توفير ميزة لغوية مماثلة، ولكنها ليست مكافئة، بواسطة كلمة المفتاح المعدلة للوصول internal في لغة C#، والتي تسمح للفئات داخل نفس التجميع بالوصول إلى الأماكن الخاصة أو الأجزاء الخاصة للفئات الأخرى. يتوافق هذا مع وضع علامة على كل فئة كصديق أو كغيره لفئة أخرى في نفس التجميع؛ فئات الأصدقاء أكثر دقة واشمل.

سيتعين على لغات البرمجة التي تفتقر إلى دعم فئات الأصدقاء أو العائلة التي لها علاقة فيما بينها، أو ميزة لغوية مماثلة، تنفيذ حلول بديلة لتحقيق واجهة آمنة تعتمد على الأجزاء لهيكل البيانات. ومن أمثلة هذه الحلول البديلة:

 جعل حقول الأجزاء عامة. يقلل هذا الحل من التغليف من خلال جعل انتهاك ثوابت بنية البيانات من الخارج أمرًا ممكنًا.
 نقل جميع البيانات الهيكلية القابلة للتغيير بعيدًا عن الجزء إلى بنية البيانات، وإدخال التوجيه غير المباشر مرة أخرى من كل جزء إلى بنية البيانات الخاصة به. يؤدي هذا الحل إلى تغيير تنظيم بنية البيانات، ويزيد من استهلاك الذاكرة في الحالات التي لا تكون فيها هناك حاجة لهذه المعلومات.

 ملكيات 

 الصداقات ليست متناظرة, إذا كانت الفئة A صديقة للفئة B ، فإن الفئة B لا تكون صديقة للفئة A تلقائيًا.
 الصداقات ليست عابرة ,إذا كانت الفئة A صديقة للفئة B ، والفئة B صديقة للفئة C ، فإن الفئة A ليست صديقة للفئة C تلقائيًا.
 الصداقات لا تورث، إذا كانت الفئة Base صديقة للفئة X، فإن الفئة الفرعية Derived ليست صديقة للفئة X تلقائيًا؛ وإذا كانت الفئة X صديقة للفئة Base، فإن الفئة X ليست صديقة للفئة الفرعية Derived تلقائيًا. ومع ذلك، إذا كانت الفئة Y صديقة للفئة الفرعية Derived، فسيكون للفئة Y أيضًا إمكانية الوصول إلى الأجزاء المحمية من الفئة Base، تمامًا كما تفعل الفئة الفرعية Derived.

 مراجع 

 روابط خارجية 

 http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr043.htm
 http://www.cplusplus.com/doc/tutorial/inheritance/

تصنيف:صنف (حوسبة)