طريقة الطفرات
في علوم الحاسوب ، تُستخدم طريقة التعديل للتحكم في التغييرات التي تطرأ على متغير. وتُعرف أيضًا باسم طرق التعيين . غالبًا ما تُصاحب طريقة التعيين طريقة جلب تُعيد قيمة المتغير الخاص. وتُعرف هاتان الطريقتان مجتمعتين باسم دوال الوصول .
تُستخدم طريقة التعديل غالبًا في البرمجة كائنية التوجه ، تماشيًا مع مبدأ التغليف . وفقًا لهذا المبدأ، تُجعل متغيرات الأعضاء في الصنف خاصة لإخفائها وحمايتها من التعليمات البرمجية الأخرى، ولا يمكن تعديلها إلا بواسطة دالة عضو عامة (طريقة التعديل)، والتي تأخذ القيمة الجديدة المطلوبة كمعامل، وتتحقق من صحتها اختياريًا، ثم تُعدّل متغير العضو الخاص . يمكن مقارنة طرق التعديل بتحميل عامل التعيين الزائد، ولكنها تظهر عادةً في مستويات مختلفة من التسلسل الهرمي للكائنات.
يمكن استخدام دوال التعديل حتى في بيئات البرمجة غير الكائنية. في هذه الحالة، يُمرر مرجع إلى المتغير المراد تعديله إلى دالة التعديل، بالإضافة إلى القيمة الجديدة. في هذه الحالة، لا يستطيع المُصرّف منع الكود من تجاوز دالة التعديل وتغيير المتغير مباشرةً. تقع مسؤولية ضمان تعديل المتغير فقط من خلال دالة التعديل، وليس تعديله مباشرةً، على عاتق المطورين .
في لغات البرمجة التي تدعمها، توفر الخصائص بديلاً مناسباً دون التخلي عن فائدة التغليف.
في الأمثلة أدناه، يمكن لطريقة التعديل المنفذة بالكامل أيضًا التحقق من صحة بيانات الإدخال أو اتخاذ إجراءات أخرى مثل تشغيل حدث ما .
تداعيات
البديل عن تعريف دوال التعديل والوصول، أو كتل الخصائص ، هو منح متغير النسخة مستوى رؤية غير خاص، والوصول إليه مباشرةً من خارج الكائنات. يُمكن التحكم بدقة أكبر في حقوق الوصول باستخدام دوال التعديل والوصول. على سبيل المثال، يُمكن جعل مُعامل للقراءة فقط ببساطة عن طريق تعريف دالة وصول دون تعريف دالة تعديل. قد يختلف مستوى رؤية الدالتين؛ فمن المفيد غالبًا أن تكون دالة الوصول عامة، بينما تظل دالة التعديل محمية، أو خاصة بالحزمة، أو داخلية.
يُتيح الجزء الذي يُعرّف فيه المُعدِّل فرصةً للتحقق من صحة البيانات الواردة أو معالجتها مسبقًا. إذا كان الوصول الخارجي مضمونًا عبر المُعدِّل، فلا يُمكن تجاوز هذه الخطوات. على سبيل المثال، إذا مُثِّل التاريخ بمتغيرات خاصة منفصلة ، yearفيمكن للمُعدِّل تقسيم التواريخ الواردة، بينما يتم الوصول إلى نفس متغيرات النسخة الخاصة من خلال المُعدِّل لضمان الاتساق . في جميع الحالات، يُمكن رفض قيم الأشهر التي تقع خارج النطاق من 1 إلى 12 بواسطة نفس الكود.monthdaysetDatesetYearsetMonth
تتيح دوال الوصول، على النقيض من ذلك، توليد تمثيلات بيانات مفيدة من المتغيرات الداخلية مع الحفاظ على بنيتها مغلفة ومخفية عن الوحدات الخارجية. فعلى سبيل المثال، getAmountقد تقوم دالة وصول مالية بإنشاء سلسلة نصية من متغير رقمي، حيث يُحدد عدد المنازل العشرية بواسطة currencyمُعامل مخفي.
تُتيح لغات البرمجة الحديثة غالبًا إمكانية إنشاء الشيفرة الأساسية للمُعدِّلات والمُوصِّلات في سطر واحد ، كما هو الحال في لغتي C# public string Name { get; set; }وRuby attr_accessor :name. في هذه الحالة، لا يتم إنشاء أي كتل برمجية للتحقق من الصحة أو المعالجة المسبقة أو التركيب. مع ذلك، تحتفظ هذه المُوصِّلات المُبسَّطة بميزة التغليف مقارنةً بمتغيرات النسخ العامة البسيطة، ولكن من الشائع أنه مع تطور تصميمات الأنظمة ، وصيانة البرمجيات ، وتغير المتطلبات، تصبح متطلبات البيانات أكثر تعقيدًا. في النهاية، يتم استبدال العديد من المُعدِّلات والمُوصِّلات التلقائية بكتل برمجية منفصلة. تكمن فائدة إنشائها تلقائيًا في المراحل الأولى من التنفيذ في أن الواجهة العامة للفئة تظل كما هي سواءً أُضيفت إليها تعقيدات أم لا، مما لا يتطلب إعادة هيكلة شاملة في حال إضافتها. [ 1 ]
غالبًا ما يتطلب التعامل مع المعاملات التي تحتوي على دوال تعديل ووصول من داخل الفئة التي تُعرَّف فيها بعض التفكير الإضافي. في المراحل الأولى من التنفيذ، عندما يكون هناك القليل من التعليمات البرمجية الإضافية أو لا توجد أي تعليمات برمجية إضافية في هذه الكتل، لا يهم ما إذا تم الوصول إلى متغير النسخة الخاص مباشرةً أم لا. مع إضافة التحقق من الصحة، والتحقق المتبادل ، وفحوصات سلامة البيانات ، والمعالجة المسبقة، أو غيرها من التحسينات، قد تظهر أخطاء دقيقة حيث تستخدم بعض عمليات الوصول الداخلية التعليمات البرمجية الأحدث بينما يتم تجاوزها في أماكن أخرى.
قد تكون وظائف الوصول أقل كفاءة من جلب حقول البيانات أو تخزينها مباشرة بسبب الخطوات الإضافية المتضمنة، [ 2 ] ومع ذلك، غالبًا ما يتم تضمين هذه الوظائف مما يلغي الحمل الزائد لاستدعاء الوظيفة.
أمثلة
![]()
حَشد
عمر الطالب ( بالأيام) ؟ نهاية الطالب.code student_get_age proc object : DWORD mov ebx , object mov eax , student.age [ ebx ] ret student_get_age endpإجراء student_set_age : كائن : DWORD ، العمر : DWORD، نقل الكائن إلى ebx ، نقل العمر إلى eax ، نقل عمر الطالب إلى [ ebx ]، eax، إرجاع student_set_age .ج
في الملف Student.h :
دبراغما مرة واحدةstruct Student ; /* بنية مبهمة */ typedef struct Student Student ;إنشاء طالب ( العمر ، الاسم ) ؛ تدمير طالب ( طالب ) .void setStudentAge ( Student * s , int age ); int getStudentAge ( const Student * s ); char * getStudentName ( const Student * s );في الملف Student.c :
#include <stdlib.h> #include <string.h>#include "Student.h"struct Student { int age ; char * name ; };Student * createStudent ( int age , const char * name ) { Student * s = ( Student * ) malloc ( sizeof ( Student )); s -> name = strdup ( name ); s -> age = age ; return s ; }void destroyStudent ( const Student * s ) { free ( s -> name ); free ( s ); }void setStudentAge ( Student * s , int age ) { s -> age = age ; }int getStudentAge ( const Student * s ) { return s -> age ; }char * getStudentName ( const Student * s ) { return s -> name ; }في الملف Main.c :
#include <stdio.h>#include "Student.h"int main ( void ) { Student * s = createStudent ( 19 , "Maurice" ); char * name = getStudentName ( s ); int old_age = getStudentAge ( s ); printf ( "%s's old age = %i \n " , name , old_age ); setStudentAge ( s , 21 ); int new_age = getStudentAge ( s ); printf ( "%s's new age = %i \ n " , name , new_age ); destroyStudent ( s ); return 0 ; }في ملف Makefile:
all : out.txt ; cat $ < out.txt : main ; ./$ < > $ @ main : Main.o Student.o Main.o Student.o : Student.h clean :; $ ( RM ) * .o out.txt mainلغة سي++
في ملف Student.cppm :
استيراد std ؛باستخدام std :: string ;class Student { private : string name ; public : Student ( const string & name ) : name { name } {}[[ nodiscard ]] const string & getName () const noexcept { return name ; }void setName ( const string & name ) noexcept { this -> name = name ; } };سي شارب
يوضح هذا المثال مفهوم الخصائص في لغة C# ، وهي نوع خاص من أعضاء الفئة . على عكس لغة Java، لا يتم تعريف أي دوال صريحة؛ إذ تحتوي "الخاصية" العامة على منطق معالجة الإجراءات. لاحظ استخدام المتغير المدمج (غير المُعلن) .value
public class Student { private string name ;/// <summary> /// الحصول على اسم الطالب أو تعيينه /// </summary> public string Name { get { return name ; } set { name = value ; } } }في الإصدارات اللاحقة من لغة C# (.NET Framework 3.5 وما فوق)، يمكن اختصار هذا المثال على النحو التالي، دون تعريف المتغير الخاص name.
public class Student { public string Name { get ; set ; } }استخدام الصيغة المختصرة يعني أن المتغير الأساسي لم يعد متاحًا من داخل الفئة. ونتيجةً لذلك، setيجب أن يكون جزء الخاصية موجودًا لإسناد القيمة إليه. ويمكن تقييد الوصول باستخدام setمُعدِّل وصول خاص.
public class Student { public string Name { get ; private set ; } }لغة الشفرة الشائعة
في نظام كائنات Common Lisp ، يمكن لمواصفات الفتحات ضمن تعريفات الفئات تحديد أي من الخيارات :reader` <sub>read</sub>` :writerو` :accessor<sub>set</sub>` و`<sub>accessor</sub>` (حتى عدة مرات) لتعريف طرق القراءة، وطرق التعيين، وطرق الوصول (طريقة قراءة والطريقة المقابلة لها setf). [ 3 ] يمكن الوصول إلى الفتحات دائمًا مباشرةً من خلال أسمائها باستخدام `<sub>read</sub>` with-slotsو` slot-value<sub>setor</sub>`، وتُعرّف خيارات الوصول إلى الفتحات طرقًا متخصصة تستخدم `<sub>read</sub>` slot-value. [ 4 ]
لا يمتلك نظام CLOS نفسه مفهوم الخصائص، على الرغم من أن امتداد بروتوكول MetaObject يحدد وسائل الوصول إلى أسماء وظائف القراءة والكتابة الخاصة بالفتحة، بما في ذلك تلك التي تم إنشاؤها باستخدام :accessorالخيار. [ 5 ]
يوضح المثال التالي تعريفًا لفئة الطلاب باستخدام خيارات الفتحات هذه والوصول المباشر إلى الفتحات:
( defclass student () (( name :initarg :name :initform "" :accessor student-name ) ; student-name is setf'able ( birthdate :initarg :birthdate :initform 0 :reader student-birthdate ) ( number :initarg :number :initform 0 :reader student-number :writer set-student-number )))مثال على دالة جلب خاصية محسوبة (هذه مجرد دالة) ( defmethod student-age (( self student )) ( - ( get-universal-time ) ( student-birthdate self )))مثال على الوصول المباشر إلى خانة ضمن مُعدِّل خاصية محسوبة ( defmethod ( setf student-age ) ( new-age ( self student )) ( with-slots ( birthdate ) self ( setf birthdate ( - ( get-universal-time ) new-age )) new-age ))تُنشئ خيارات الوصول إلى الخانات طرقًا، مما يسمح بتعريف طرق إضافية ( defmethod set-student-number :before ( new-number ( self student )) ؛ يمكنك أيضًا التحقق مما إذا كان هناك طالب بالرقم الجديد موجودًا بالفعل. ( check-type new-number ( integer 1 * )))د
تدعم لغة D صيغة دوال الوصول والتعديل. في الإصدار الثاني من اللغة، يجب أن تحتوي دوال الوصول والتعديل في الأصناف/الهياكل @propertyعلى السمة. [ 6 ] [ 7 ]
class Student { private string name_ ;// دالة جلب القيمة @property string name () { return this . name_ ; }// دالة التعيين @property string name ( string name_in ) { return this . name_ = name_in ; } }Studentيمكن استخدام مثال على النحو التالي :
Student s = new Student ; s.name = " David" ; // نفس تأثير student.name("David") string student_name = s.name ; // نفس تأثير student.name ( )دلفي
هذا صنف بسيط في لغة دلفي يوضح مفهوم الملكية العامة للوصول إلى حقل خاص.
واجهة المستخدمtype TStudent = class strict private FName : string ; procedure SetName ( const Value : string ) ; public /// <summary> /// الحصول على اسم الطالب أو تعيينه. /// </summary> property Name : string read FName write SetName ; end ;// ...تطبيقالإجراء TStudent.SetName ( const Value : string ) ; ابدأ FName : = Value ; نهاية ;نهاية .جافا
في هذا المثال لفئة بسيطة تمثل طالبًا مع تخزين الاسم فقط، يمكن للمرء أن يرى أن اسم المتغير خاص، أي مرئي فقط من فئة الطالب، وأن "setter" و "getter" عامان، وهما طريقتي " " و " ".getName()setName(name)
public class Student { private String name ;public String getName () { return name ; } public void setName ( String name ) { this . name = name ; } }جافا سكريبت
في هذا المثال، يتم استخدام دالة البناء Studentلإنشاء كائنات تمثل طالبًا مع تخزين الاسم فقط.
دالة الطالب ( الاسم ) { متغير _الاسم = الاسم ؛this.getName = function ( ) { return _name ; } ;this.setName = function ( value ) { _name = value ; } ; }أو (باستخدام طريقة قديمة لتعريف أدوات الوصول في متصفحات الويب): [ 8 ]
دالة الطالب ( الاسم ) { متغير _الاسم = الاسم ؛ هذا .__ defineGetter__ ( 'الاسم' , دالة () { إرجاع _الاسم ؛ }); هذا .__ defineSetter__ ( 'الاسم' , دالة ( القيمة ) { _الاسم = القيمة ؛ }); }أو (باستخدام النماذج الأولية للوراثة وصيغة الوصول ES6 ):
دالة الطالب ( الاسم ) { هذا._الاسم = الاسم ؛ }Student.prototype = { get name ( ) { return this._name ; } , set name ( value ) { this._name = value ; } } ;أو (بدون استخدام النماذج الأولية):
var Student = { get name () { return this . _name ; }, set name ( value ) { this . _name = value ; } };أو (باستخدام defineProperty):
دالة الطالب ( الاسم ) { this._name = الاسم ؛ } كائن . تعريف الخاصية ( الطالب . النموذج الأولي ، 'الاسم ' ، { الحصول : دالة ( ) { إرجاع this._name ؛ } ، تعيين : دالة ( القيمة ) { this._name = القيمة ؛ } } ) ;ActionScript 3.0
package { public class Student { private var _name : String ; public function get name () : String { return _name ; }public function set name ( value : String ) : void { _name = value ; } } }أوبجكتيف سي
باستخدام صيغة Objective-C 1.0 التقليدية، مع عدّ المراجع يدويًا كما هو الحال في GNUstep على Ubuntu 12.04 :
@interface Student : NSObject { NSString * _name ; }- ( NSString * ) name ; - ( void ) setName: ( NSString * ) name ;@نهايةطالب @implementation- ( NSString * ) name { return _name ; }- ( void ) setName: ( NSString * ) name { [ _name release ]; _name = [ name retain ]; }@نهايةباستخدام صيغة Objective-C 2.0 الأحدث كما هو مستخدم في Mac OS X 10.6 و iOS 4 و Xcode 3.2، يتم إنشاء نفس الكود الموضح أعلاه:
@interface Student : NSObject@property ( nonatomic , retain ) NSString * name ;@نهايةطالب @implementation@synthesize name = _name ;@نهايةوابتداءً من نظام التشغيل OS X 10.8 ونظام التشغيل iOS 6 ، وباستخدام Xcode 4.4 والإصدارات الأحدث، يمكن تبسيط بناء الجملة بشكل أكبر:
@interface Student : NSObject@property ( nonatomic , strong ) NSString * name ;@نهايةطالب @implementationلا شيء يدخل هنا، وهذا أمر طبيعي.@نهايةبيرل
حزمة الطالب ؛sub new { bless {}, shift ; }sub set_name { my $self = shift ; $self -> { name } = $_ [ 0 ]; }sub get_name { my $self = shift ; return $self -> { name }; }1 ؛أو باستخدام Class::Accessor
الحزمة Student ؛ استخدم qw الأساسي (Class::Accessor) ؛ __PACKAGE__ -> اتبع أفضل الممارسات ؛الطالب -> mk_accessors ( qw(name) );1 ؛أو باستخدام نظام كائنات موس :
حزمة الطالب ؛ استخدم موس ؛يستخدم Moose اسم السمة كدالة تعيين واسترجاع، وتسمح لنا خصائص القراءة والكتابة بتجاوز ذلك وتوفير أسماء خاصة بنا، في هذه الحالة get_name و set_name لهما ' name' => ( is => 'rw' , isa => 'Str' , reader => 'get_name' , writer => 'set_name' );1 ؛PHP
تُعرّف لغة PHP "الأساليب السحرية" __getوخصائص __setالكائنات. [ 9 ]
في هذا المثال لفئة بسيطة تمثل طالبًا مع تخزين الاسم فقط، يمكن للمرء أن يرى أن اسم المتغير خاص، أي مرئي فقط من فئة الطالب، وأن "setter" و "getter" عامان، وهما الطريقتان و .getName()setName('name')
class Student { private string $name ;/** * @return string الاسم. */ public function getName () : string { return $this -> name ; }/** * @param string $newName الاسم المراد تعيينه. */ public function setName ( string $newName ) : void { $this -> name = $newName ; } }بايثون
يستخدم هذا المثال فئة بايثون تحتوي على متغير واحد، ودالة جلب، ودالة تعيين.
class Student : _name : str# دالة التهيئة def __init__ ( self , name : str ) -> None : # متغير مثيل لتخزين اسم الطالب self . _name = name# دالة الوصول @property def name ( self ) -> str : return self . _name# دالة التعيين @ name.setter def name ( self , new_name : str ) - > None : self._name = new_nameطالب : طالب = طالب ( "بوب" ) طباعة ( اسم الطالب ) # يطبع: بوبstudent.name = "Alice " print ( student.name ) # يطبع : Alicestudent._name = "Charlie" # تجاوز دالة التعيين print ( student._name ) # تجاوز دالة الجلب # يطبع : Charlieمضرب
في لغة Racket ، يُعد نظام الكائنات طريقةً لتنظيم الشيفرة البرمجية، وهو إضافةٌ إلى الوحدات النمطية والوحدات البرمجية. وكما هو الحال في بقية اللغة، يتمتع نظام الكائنات بقيم من الدرجة الأولى، ويُستخدم النطاق المعجمي للتحكم في الوصول إلى الكائنات والأساليب.
#lang racket ( define student% ( class object% ( init-field name ) ( define/public ( get-name ) name ) ( define/public ( set-name! new-name ) ( set! name new-name )) ( super-new )))( define s ( new student% [ name "Alice" ])) ( send s get-name ) ; => "Alice" ( send s set-name! "Bob" ) ( send s get-name ) ; => "Bob"تُعدّ تعريفات البنية طريقة بديلة لتعريف أنواع جديدة من القيم، مع وجود المُعدِّلات عند الحاجة إليها صراحةً:
#lang racket ( struct student ( name ) #:mutable ) ( define s ( student "Alice" )) ( set-student-name! s "Bob" ) ( student-name s ) ; => "Bob"روبي
في لغة روبي ، يمكن تعريف طرق الوصول والتعديل الفردية، أو يمكن استخدام بنيات البرمجة الوصفية للإعلان عن متغير خاص في فئة ولتوفير الوصول العام للقراءة فقط أو القراءة والكتابة إليه على التوالي.attr_readerattr_accessor
يُتيح تحديد طرق الوصول والتعديل الفردية مساحةً للمعالجة المسبقة للبيانات أو التحقق من صحتها.
class Student def name @name enddef name= ( value ) @name = value end endإمكانية الوصول العام البسيط للقراءة فقط إلى @nameالمتغير الضمني
class Student attr_reader :name endإمكانية الوصول العام البسيط للقراءة والكتابة إلى @nameالمتغير الضمني
class Student attr_accessor :name endالصدأ
struct Student { name : String , }impl Student { fn name ( & self ) -> & String { & self . name }fn name_mut ( & mut self ) -> & mut String { & mut self . name } }أحاديث قصيرة
العمر: رقم aNumber "اضبط عمر المستلم على aNumber إذا كان أكبر من 0 وأقل من 150" ( رقم aNumber بين: 0 و: 150 ) إذا كان صحيحًا: [ العمر := رقم aNumber ] سويفت
class Student { private var _name : String = ""var name : String { get { return self . _name } set { self . _name = newValue } } }فيجوال بيسك دوت نت
يوضح هذا المثال مفهوم الخصائص في لغة VB.NET، والتي تُستخدم في الفئات. وكما هو الحال في لغة C#، يوجد استخدام صريح للأساليب ` Getand` Set.
طالب في الفصل العامPrivate _name As Stringاسم الخاصية العامة () الحصول على إرجاع _name نهاية الحصول على تعيين ( بواسطة القيمة قيمة ) _name = القيمة نهاية التعيين نهاية الخاصيةنهاية الفئةفي VB.NET 2010، يمكن استخدام الخصائص المُنفذة تلقائيًا لإنشاء خاصية دون الحاجة إلى استخدام صيغتي Get و Set. لاحظ أن المُصرّف يُنشئ متغيرًا مخفيًا، يُسمى _name، ليتوافق مع الخاصية name. استخدام متغير آخر داخل الفئة يحمل نفس الاسم _nameسيؤدي إلى خطأ. يتوفر الوصول المُميز إلى المتغير الأساسي من داخل الفئة.
فئة عامة طالب خاصية عامة اسم كسلسلة نصية نهاية الفئةانظر أيضاً
مراجع
- ↑ ستيفن فوكوا (2009). "الخصائص التلقائية في لغة سي شارب 3.0" . تم الاطلاع عليه بتاريخ 19-10-2009 .
{{cite web}}: CS1 maint: deprecated archiveal service ( link ) - ↑ تيم لي (1998-07-13). "كفاءة وقت التشغيل لوظائف الوصول" .
- ↑ "CLHS: Macro DEFCLASS" . تم الاطلاع عليه بتاريخ 29-03-2011 .
- ↑ "CLHS: 7.5.2 الوصول إلى الفتحات" . تم الاسترجاع في 29-03-2011 .
- ↑ "MOP: تعريفات الفتحات" . تم الاسترجاع في 29-03-2011 .
- ↑ "الدوال - لغة البرمجة D" . تم الاطلاع عليه بتاريخ 13-01-2013 .
- ↑ "أسلوب دي" . تم الاطلاع عليه بتاريخ 2013-02-01 .
- ↑ "Object.prototype.__defineGetter__() - JavaScript | MDN" . developer.mozilla.org . تم الاطلاع عليه بتاريخ 2021-07-06 .
- ↑ "PHP: التحميل الزائد - دليل المستخدم" . www.php.net . تم الاطلاع عليه بتاريخ 2021-07-06 .
- طريقة (برمجة الحاسوب)
