تنصل
لا تشير المقالة ضمنًا إلى أي منظور جديد جوهريًا للأشياء ، إلا من وجهة نظر دراسة هذه المادة من "الصفر المطلق".

تستند المادة إلى ملاحظات من حوالي 7 سنوات ، عندما كان طريقي في دراسة OOP بدون تعليم تكنولوجيا المعلومات قد بدأ للتو. في تلك الأيام كانت MATLAB هي اللغة الرئيسية ، وبعد ذلك بوقت طويل تحولت إلى C #.
عرض مبادئ OOP ، الذي وجدته ، مع أمثلة في شكل بعض التفاح ، والكمثرى الموروثة من فئة "الفاكهة" ومجموعة من المصطلحات (الوراثة ، تعدد الأشكال ، التغليف ، إلخ) ، كان يُنظر إليه على أنه حرف صيني.
على العكس من ذلك ، الآن لسبب ما أرى مثل هذه المواد بشكل طبيعي ، ويبدو العرض التقديمي من مقالتي في بعض الأحيان مربكًا وطويلًا.
لكن ملاحظاتي القديمة والشفرة الرهيبة الباقية على الهولوديسك في pipboy تُظهر أن العرض "الكلاسيكي" لم يفي بوظائفه في ذلك الوقت ، وكان غير ناجح تمامًا. ربما هناك شيء ما في هذا.
إلى أي مدى يتوافق هذا مع الواقع وتفضيلاتك الخاصة - قرر بنفسك ...
الشروط المسبقة لـ OOP
كود الحائط
عندما بدأت للتو في الكتابة بلغة MATLAB'e ، كانت الطريقة الوحيدة للكتابة وعرفت كيف. كنت أعرف عن الوظائف وأن البرنامج يمكن تقسيمه إلى أجزاء.
كان المصيد أن جميع الأمثلة تمتص. فتحت كتابًا دراسيًا لشخص ما ، ورأيت هناك وظائف جسدية صغيرة تتكون من 2-3 سطور ، وإجمالاً كل هذا لم ينجح (كان هناك شيء مفقود) ، ولم ينجح إلا عندما أعدت تجميع القمامة في "جدار".
ثم كتبت بعض البرامج الصغيرة عدة مرات ، وفي كل مرة كنت أتساءل عن سبب وجود شيء لأشاركه. ولم يأتِ الفهم إلا لاحقًا: الرمز "الجدار" هو الحالة الطبيعية لبرنامج يبلغ حوالي 1.5 صفحة مقاس A4. لا توجد وظائف ، ولا قدر الله ، ليست هناك حاجة إلى OOP.
هكذا يبدو نص ماتلاب (مأخوذ من الإنترنت).
Fs = 1000; % Sampling frequency
T = 1/Fs; % Sample time
L = 1000; % Length of signal
t = (0:L-1)*T; % Time vector
% Sum of a 50 Hz sinusoid and a 120 Hz sinusoid
%x = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
%y = x + 2*randn(size(t)); % Sinusoids plus noise
y=1+sin(100*pi*t);
plot(Fs*t(1:50),y(1:50))
title('Signal Corrupted with Zero-Mean Random Noise')
xlabel('time (milliseconds)')
figure
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Y = fft(y,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
% Plot single-sided amplitude spectrum.
plot(f,2*abs(Y(1:NFFT/2+1)))
title('Single-Sided Amplitude Spectrum of y(t)')
xlabel('Frequency (Hz)')
ylabel('|Y(f)|')
تقسيم الكود إلى وظائف
لماذا لا يزال يتم تقسيم الكود إلى أجزاء ، لقد خمنت عندما بدأ حجمه يصبح لا يمكن تصوره تمامًا (الآن وجدت رمزًا شيتًا في الأرشيف - 650 سطرًا بجدار) ثم تذكرت الوظائف. علمت أنهم سمحوا لك بتقسيم التعليمات البرمجية الخاصة بك إلى كتل صغيرة يسهل تصحيحها وإعادة استخدامها.
لكن الحيلة مختلفة - لسبب ما ، تظل جميع المواد التعليمية صامتة حول مقدار دالة المتغيرات ... قال
مسار الرياضيات أن الوظيفة هي y = f (x)
وهذا يسمى "دالة لمتغير واحد." على سبيل المثال ، y = x 2 عبارة عن بارابول كامل!
مشكلة رياضية : قم ببناء بارابول بالنقاط. في ورقة دفتر ، في صندوق.
. z=f(x,y). — — . , .. . .

, « », . , , . – . .
-…

وإذا كانت الوظيفة بها أربعة متغيرات أو أكثر…. نظرية الأوتار الفائقة. متنوعة كالابي ياو. مميت. غير معطى. افهم ...
باختصار ، كل هذا خطأ. في البرمجة ، الحالة الطبيعية للوظيفة هي المهبل الشرجي المزدوج . يأخذ 100 متغير ويعيد نفس الشيء ، وهو أمر جيد. شيء آخر غير طبيعي - لإدراجها مع COMMA.

حول حقيقة أنه يمكنك الكتابة بطريقة مختلفة ، أدركت عندما أقوم بالبحرية هنا
function work = SelectFun(ProtName,length_line,num_length,angleN_1,angleN_2,num_angleN,angleF_1,angleF_2,num_angleF, res_max, num_res,varargin)
global angleF angleN model_initialized
مجموعة من المتغيرات مفصولة بـ COMMA. ولرمز الاستدعاء أسماء مختلفة تمامًا لهذه المعلمات ، شيء مثل SelectFun (a ، b ، c ، d….) لذلك ، عليك أن تتذكر أين يوجد المتغير. وجعل ترتيبهم من خلال COMMA. وإذا تم تحديث الكود ، وتغير عدد المتغيرات ، فيجب إعادة ترتيبها مرة أخرى باستخدام COMMA.
ولماذا كانت المتغيرات العالمية (أطلق النار!) في هذا القذارة؟
بنغو! من أجل عدم ترتيب المتغيرات مع كل ترقية رمز من خلال COMMA.
لكن الكوما كانت لا تزال تلاحقني ، كما لو كنت في كابوس.

وظهر فارارجين. هذا يعني أنه يمكنني إضافة العديد من الوسائط في كود الاستدعاء باستخدام COMMA ...
ثم فكرت في المصفوفات. تحدثت أمثلة البرنامج التعليمي بحماس عن حقيقة أن المصفوفة يمكن أن تكون مثل هذا:
=
[1 2 3
4 5 6
7 8 9]
وترى X (2،3) = 6 ، X (3،3) = 9 ، ونحن ... يمكننا تنظيم ضرب المصفوفة في مثل هذه المصفوفات! في الدرس الأخير ، مررنا بـ PARABOLS ، والآن MATRIXES….
ولا يوجد سطر واحد من هذه الكتب المدرسية القصيرة والواضح: هناك حاجة إلى المصفوفات لعمل دالة من 100 متغير ولا تسقط من إدراجها من خلال COMMA.

بشكل عام ، خطرت لي فكرة حشر كل شيء في طاولة كبيرة ثنائية الأبعاد. كل شيء سار بشكل جيد في البداية:
angles =
[angleN, angleN_1, angleN_2, num_angleN
angleF, angleF_1, angleF_2, num_angleF]
function work= SelectFun(ProtName, length_line, num_length, angles , res_max, num_res, varargin)
لكني أردت المزيد. وبدأت تبدو كما يلي:
data=
[angleN, angleN_1, angleN_2, num_angleN
angleF, angleF_1, angleF_2, num_angleF
length_line, num_length, 0, 0
res_max,num_res, 0,0]
function work= SelectFun(ProtName,data,varargin)
ويبدو أن كل شيء على ما يرام ، ولكن ... صفر! لقد ظهروا لأنني أردت تشتيت البيانات غير المتجانسة عبر خطوط مختلفة ، وكان مقدار البيانات من أنواع مختلفة مختلفًا ... وكيف يجب أن تعالج الوظيفة هذه الأصفار؟ ماذا يحدث إذا كنت أرغب في تحديث الكود؟ سأضطر إلى إعادة كتابة المعالج لهذه الأصفار السيئة داخل الوظيفة! بعد كل شيء ، قد تكون بعض المتغيرات مساوية للصفر بالفعل ...
لم أطلب هذا مطلقًا ...
بشكل عام ، هذه هي الطريقة التي تعلمت بها عن الهياكل.
الهياكل
هذا هو المكان الذي كان من الضروري فيه بدء العرض التقديمي حول طرق تعبئة البيانات. المصفوفات التي تحتوي على "طاولة" ، على ما يبدو ، نشأت أولاً تاريخيًا ، وكتبوا عنها أيضًا - في البداية. من الناحية العملية ، يمكنك العثور على الكثير من البرامج حيث تكون المصفوفات "كجدول" إما أحادية البعد ، أو لا تكون على الإطلاق.
الهيكل عبارة عن حزمة "ملف - مجلد" للبيانات ، تقريبًا على القرص الصلب لجهاز الكمبيوتر.
محرك الأقراص D: \
X (مجلد متغير - "كائن" أو "هيكل")
- a.txt (ملف متغير به بيانات - "حقل الكائن" ، حقل اللغة الإنجليزية.
يتم تخزين الرقم 5) - b.txt (يتم تخزين الرقم 10 )
- .txt
Y (مجلد فرعي متغير - "كائن")
- d.txt (يتم تخزين الرقم 2)
- e.txt
لتوضيح الأمر ، دعنا نكتب كيف سنرى المسار إلى ملف d.txt في مستكشف Windows
D: \ X \ Y \ d.txt
بعد ذلك نفتح الملف ونكتب الرقم "2" هناك.
الآن - كيف سيبدو في كود البرنامج. ليست هناك حاجة للإشارة إلى "محرك الأقراص المحلي الجذر" ، لذا فإن D: \ ببساطة ليس موجودًا ، ولن يكون لدينا امتداد ملف. أما بالنسبة للباقي ، فعادةً ما تستخدم النقطة بدلاً من البرمجة المائلة.
اتضح مثل هذا:
X.Y.d=2
%
X.a=5
X.b=10
-
X.c=X.a+X.b %.. .=5+10=15
X.Y.e=X.c*X.Y.d %.. X.Y.e=15*2=30
في ماتلاب، والهياكل ( البنية ) يمكن إنشاء الحق على الفور، دون ترك الخروج، أي الكود أعلاه قابل للتنفيذ ، يمكنك دفعه إلى وحدة التحكم وسيعمل كل شيء على الفور. ستظهر البنية على الفور ، وستتم إضافة جميع "متغيرات الملفات" و "متغيرات المجلد الفرعي" مرة واحدة. لسوء الحظ، فإنه من المستحيل أن أقول أن حوالي C #، والهيكل ( البنية تعيين) هناك من البواسير.
الهيكل هو نسبي أكثر برودة من مجموعة الجداول ، حيث بدلاً من الفهارس - نظام مجلد الملفات. الهيكل = "مجلد متغير" ، والذي يحتوي على "ملفات متغيرات" و "مجلدات متغيرات" أخرى (أي نوع من المجلدات الفرعية).
كل شيء مألوف ، كل شيء هو نفسه تمامًا كما هو الحال في الكمبيوتر والمجلدات والملفات الموجودة فيها ، فقط في الملفات لا توجد صور ، ولكن توجد أرقام (على الرغم من إمكانية الصور أيضًا)
هذه نسخة أكثر تقدمًا من تخزين البيانات لتمريرها إلى وظيفة مقارنة بفكرة إنشاء جدول صفيف ، وخاصة ثنائي الأبعاد ، ويضايقني ، tesseract ، ثلاثي الأبعاد وأكثر.
يمكن استخدام ARRAY TABLE في حالتين:في الواقع ، عادةً ما يتم استخدام ARRAY TABLE فقط كصف أحادي البعد من البيانات المتجانسة. كل شيء آخر في البرامج العادية يتم وفقًا لنظام "مجلد الملفات".
- إنه صغير (لماذا إذن؟ ماذا ، لا يمكنك تمرير وسيطات مفصولة بفواصل إلى الوظيفة؟).
- إما يمكنك عمل حلقة عليها وأتمتة البحث / الملء (هذا ليس ممكنًا دائمًا)
فلماذا تبدأ كتب البرمجة بالمصفوفات والجداول؟ !!!
باختصار ، "بعد أن اكتشفت" الهياكل بنفسي ، قررت أنني عثرت على منجم ذهب وأعدت كتابة كل شيء على وجه السرعة. بدأ رمز القرف يبدو كالتالي:
Data.anglesN=[angleN, angleN_1,angleN_2, num_angleN]; %
Data.anglesF=[angleF, angleF_1, angleF_2, num_angleF]; %
Data.length_line= length_line;
Data.num_length= num_length;
Data.res_max= res_max;
Data.num_res= num_res;
function work= SelectFun(ProtName,Data,varargin)
نعم ، يمكنك أن تفعل الكمال هنا وأن تصنع مجموعة من الأشياء المتداخلة ، لكن هذا ليس هو الهدف. الشيء الرئيسي هو أنه الآن ، داخل الدالة ، تتم فهرسة المتغير ليس برقمه الترتيبي (حيث يكون في قائمة الوسائط ، مفصولة بـ COMMA) ، ولكن بالاسم. ولا توجد أصفار غبية. واستدعاء الوظيفة الآن في شكل مقبول ، هناك أمرين فقط ، يمكنك الزفير بهدوء.
الطبقات
جلب مفهوم "الطبقة" الكثير من المصطلحات علي: التغليف ، الميراث ، تعدد الأشكال ، الطرق الثابتة ، الحقول ، الخصائص ، الطرق العادية ، المُنشئ ... # @٪ !!! ..
بسبب قلة الخبرة ، بعد أن اكتشفت الهياكل ، قررت أنه لا توجد حاجة لتعقيد الكيانات دون داع ، وفكر - "الطبقات تشبه الهياكل نفسها ، لكنها أكثر تعقيدًا."
إلى حد ما ، هو كذلك. بتعبير أدق ، هذا هو بالضبط ما هو عليه. الفصل ، إذا نظرت بعمق شديد ، هو STRUCTURE (سليل إيديولوجي لمصفوفة بواسطة جدول) ، يتم إنشاؤه عند بدء البرنامج (بشكل عام ، يبدو أنه كذلك ، وليس فقط عند بدء التشغيل). كما هو الحال في أي تابع لـ TABLE ARRAY ، يتم تخزين البيانات هناك. يمكن الوصول إليها أثناء تشغيل البرنامج.
لذلك ، كان صفي الأول شيئًا كهذا (أكتب مثالًا في C # ، لا يتم تنفيذ الحقول الثابتة عادةً في matlab ، فقط من خلال منحنى الاختراق مع المتغيرات المستمرة في وظيفة ثابتة).
public class Math{
public static double pi;
public static double e;
public static double CircleLength(double R){ //.. « »
return 2*Math.pi*R; //
}
}
الحالة المذكورة أعلاه هي مثل مهارة "أساسية" لفئة - أن تكون بغباء مصفوفة (بنية) بها بيانات. يتم إلقاء هذه البيانات فيه في بداية البرنامج ، ومن هناك يمكن استخلاصها ، بنفس الطريقة تمامًا التي سحبناها من الهيكل أعلاه. يتم استخدام الكلمة الأساسية الثابتة لهذا الغرض . يتم إنشاء
الهيكل -> في أي مكان ويخزن البيانات التي يتم إدخالها فيه في أي وقت.
الفئة -> هي الهيكل الذي يتم إنشاؤه عند بدء تشغيل البرنامج. جميع الحقول المميزة بكلمة ثابتة تقوم ببساطة بتخزين البيانات ، كما هو الحال في البنية العادية. الطرق الثابتة هي ببساطة وظائف يتم استدعاؤها من فئة ، تمامًا مثل من مجلد.
double L=Math.CircleLength(10); //L=62,8
Math.pi=4; //
كان لدي gag - إذا كانت الحقول متغيرات والطرق وظائف ، فكيف يتم تخزينها في مكان واحد؟ كما أفهمها ، فإن الوظيفة (الطريقة) في الفصل ليست في الواقع وظيفة ، ولكنها مؤشر إلى وظيفة. أولئك. هو عن نفس "المتغير" مثل باي من حيث العمل معه.
باختصار ، في البداية فهمت الفئات الموجودة في هذا المجلد بالضبط وكتبت جزءًا آخر من التعليمات البرمجية الخراء ، حيث تم استخدام الوظائف الثابتة فقط. خلاف ذلك ، كمجلد به وظائف ، لم أستخدم الفئات على الإطلاق.
تم تسهيل هذه النقطة أيضًا من خلال حقيقة أن هذه هي بالضبط طريقة عمل الفصول في MATLAB - مثل هذا المجلد الغبي الذي يبدأ اسمه بـ @ (مثل @ Math ، بدون مسافة) ، بداخله ، الملفات الحقيقية بامتداد .m هي وظائف (طرق) وهناك header مع الامتداد .m ، والذي يوضح أن وظيفة CircleLength تنتمي حقًا إلى الفئة ، وليست مجرد ملف .m مع وظيفة غير OOP تم إلقاؤها هناك.
@ Math٪ folderنعم ، هناك طريقة مألوفة أكثر للشخص العادي لكتابة فصل دراسي في ملف .m واحد ، لكن في البداية لم أكن أعرف عنه. الحقول الثابتة في matlab ثابتة فقط ، وتتم كتابتها مرة واحدة عند بدء البرنامج. ربما من أجل الحماية من "trawl" ، التي تقرر تعيين Math.pi = 4 (IMHO ، موضوع عديم الفائدة وغبي على الإطلاق ، لن يكتب أي شخص عادي مشروعًا كبيرًا في matlab ، وسيقوم مبرمج بتصحيح مشروع صغير وبالتالي ، فمن غير المحتمل انه مغفل).
- Math.m٪ header file
- ملف الدالة CircleLength.m٪
لكن العودة الى هذا الموضوع. بالإضافة إلى الطرق الثابتة ، يحتوي الفصل أيضًا على مُنشئ. المُنشئ هو في الأساس مجرد وظيفة مثل y = f (x) أو حتى y = f (). قد لا تحتوي على وسيطات إدخال ، ويجب أن تكون هناك وسيطات إخراج ، وهذا دائمًا هيكل جديد (مصفوفة).
ما الذي يفعله المنشئ. هو فقط يصنع الهياكل. منطقيا يبدو مثل هذا:
| كود C # | المكافئ المنطقي التقريبي (Pseudocode)
|
|---|---|
|
|
|
|
شيت كود على matlab ، مما يجعل هياكل مماثلة دون أي فئات (حيث يوجد الفصل - انظر أدناه):
function Y=MyClass() % MyClass, Y=F()
Y.a=5
Y.b=10
end
… -
Y=MyClass()
وعند الإخراج لدينا الهيكل
ص (متغير المجلد)من هذا ، في الواقع ، من الواضح أن ما يسمى بحقول الفئة (ليست ثابتة ، بدون رمز المفتاح الثابت ) هي متغيرات محلية تم الإعلان عنها داخل دالة المُنشئ. حقيقة أنها مكتوبة لنوع من الشيطان ليس في المنشئ ، ولكن في الخارج ، هي سكر متزامن.
- أ (متغير الملف ، يساوي 5)
- ب (متغير الملف يساوي 10)
SYNTAX SUGAR - مثل هذه الميزات الهراء للغة البرمجة ، عندما تبدأ الشفرة في الظهور كما لو كانت تريد تشويشها بشكل صحيح عند كتابتها. ولكن من ناحية أخرى ، تصبح أقصر وأسرع (من المفترض) مكتوبة.
بعد أن قمت بهذا "الاكتشاف" ، كنت ، التي كتبت في ذلك الوقت فقط في Matlab ، فوجئت بشكل لا يصدق.
في matlab ، كما كتبت أعلاه ، يمكن إنشاء هذه الهياكل في مكانها ، دون أي منشآت ، ببساطة عن طريق كتابة Ya = 5 ، Yb = 10، مثلك تمامًا في نظام التشغيل يمكنك إنشاء ملفات ومجلدات دون مغادرة السجل النقدي.
وهنا - نوع من "المُنشئ" ، وجميع حقول الهيكل (في matlab يطلق عليها خصائص - الخصائص ، على الرغم من أن الخصائص ، بالمعنى الدقيق للكلمة ، أكثر تعكيرًا من الحقول) يجب كتابتها بشكل بيروقراطي في ملف الرأس. لاجل ماذا؟ الفائدة الوحيدة التي رأيتها بعد ذلك في هذا النظام هي أن حقول الهيكل محددة مسبقًا ، وهذا يشبه "التوثيق الذاتي" - يمكنك دائمًا رؤية ما يجب أن يكون موجودًا وما لا يجب أن يكون موجودًا. هذه هي الطريقة التي أتعامل بها بعد ذلك:
classdef MyClass
properties %
a
b
end
methods %
function Y=MyClass() % .
% () Y a, b
Y.a=5;
Y.b=10;
end
end
methods (Static) %
function y=f(x) %
y=x^2; % , !11
end
end
end
أولئك. لقد فهمت كل شيء بشكل صحيح: الأساليب ثابتة فقط ، مُنشئ xs هو لما (مكتوب في الوثائق - أوه ، يجب أن يكون للفصول مُنشئ - حسنًا ، ها هو مُنشئ لك) ، كل شيء آخر لم أكن أعرفه بغباء وقررت أنني أعرف Zen و OOP.
ولكن مع ذلك ، بدت لي فكرة رائعة لتجميع الوظائف (الطرق الثابتة) عن طريق مجلدات الفئات. كان هناك الكثير منهم ، وجلست لكتابة تعليمات برمجية سيئة.
بيروقراطية
وواجهت مثل هذا الشيء. هناك مجموعة من الوظائف لمستوى أدنى من المنطق (فهي ثابتة ومعبأة في مجلدات فئات ، والآن سنحذف أسماء الفئات):
Y1=f1(X1);
Y2=f2(X2);
Y3=f2(X3);
…
Y20=f20(X20);
في المشاريع الصغيرة ، من المستحيل تحقيق مثل هذه الهيمنة على الوظائف ، تحتوي الأمثلة التعليمية بشكل عام على 2-3 وظائف - مثل "انظر كيف يمكننا بناء بارابول".
وهنا - سحابة من الوظائف ، ولكل منها ، والدتها ، حجة ناتجة ، وماذا تفعل بها جميعًا؟ ضع وظائف ذات مستوى أعلى ("رائد") من المنطق! عادة ما يكون عددهم أقل بكثير (تقليديًا ، 5 بدلاً من 20). أولئك. بشكل مشروط ، عليك أن تأخذ هذه السنوات Y1 و Y2 و Y3… .Y20 و RIPPED في بعض Z1 و Z2… Z5. حتى تتمكن لاحقًا من عقد اجتماع للحزب وفيه:
A1=g1(Z1);
A2=g2(Z2);
…
A5=g5(Z5);
% , . , !
لكن Z1… Z5 لا يأتي من تلقاء نفسه. لإنشائها ، تحتاج إلى FUNCTIONS-PACKERS. بشكل تقليدي ، يعملون شيئًا كهذا ...
function Z1=Repack1(Y1,Y7, Y19)
Z1.a=Y1.a+Y7.b*Y.19.e^2;
Z1.b=Y7.c-Y19.e;
%.... - Y1, Y7, Y19
% Z1.
% Z2…Z5,
% 4 . !
end
ومن ثم قد يكون هناك مستوى "إدارة" آخر ...
باختصار ، أدركت أنني كنت في جحيم لوجستي. لا يمكنني عادةً استخراج البيانات من FIGURE CLOUD للوظائف الصغيرة y = f (x) دون كتابة FIGURE CLOUD لوظائف إعادة التغليف البيروقراطية ، وعندما يتم نقل البيانات إلى مستوى أعلى ، نحتاج إلى المزيد من البدائل. البرنامج النهائي مليء بالبيروقراطية من خلال وعبر - هناك عدد أكبر من أجهزة إعادة التجميع غير "كود الأعمال". لا تحل فئات المجلد مقابل الوظائف هذه المشكلة - فهي تجمع فقط أجهزة إعادة التجميع البيروقراطية الحمقاء في أكوام.
ثم قررت تحديث هذا الرمز الغامض ، واتضح أنه بدون نشر الجزء البيروقراطي بأكمله ، هذا مستحيل!
تمامًا مثل الحياة في روسيا ...
أدركت أنني كنت أفعل شيئًا خاطئًا ، وفهمت OOP بشكل أفضل. والحل - إذا نظرت إلى الأمر بهذه الطريقة ، كان ظاهريًا أيديولوجيًا.
فكرة OOP
لماذا تقوم مجموعة من الوظائف مثل y = f (x) التي تنتج وسيطات إخراج مختلفة Y1… .Y20 ، بينما يمكنك إنشاء وسيطة واحدة. نوعا ما:
Y_all=f1(Y_all, X1);
Y_all=f2(Y_all, X2);
….
Y_all=f20(Y_all, X20);
بعد ذلك ، سيتم دفع جميع نتائج الوظائف تمامًا في بنية واحدة ، في مصفوفة واحدة ، فقط في أقسامها المختلفة. الكل. ثم Y_all يمكن نقلها مباشرة إلى الأعلى ، إلى المستوى الأعلى من "الإدارة".
Y_all=DO_MOST_IMPORTANT_SHIT(Y_all, options_how_to_do_this_shit)
الكل-الكل-كل الوظائف- الخاطفون-المشغلات يذهبون إلى المؤخرة! يتم جمع جميع البيانات في قاعدة واحدة Y_all ، وتضع جميع الوظائف ذات المستوى المنخفض ثمار عمالها في أقسام Y_all مختلفة ، و "الإدارة" من خلال جميع حجرات Y_all وتفعل ما يجب أن تفعله. لا شيء غير ضروري ، الكود مكتوب بسرعة ويعمل بشكل رائع ...
هذه بالضبط فكرة OOP وتتكون. في الكتب المدرسية ، يكتبون أمثلة تعليمية عن التفاح والكمثرى ، ثم يعرضون برنامجًا في 5 أسطر. ليست هناك حاجة لأي OOP على الإطلاق ، في أمثلة 5 أسطر ، منذ ذلك الحين يتم نقل البيانات إلى "مستوى الإدارة العليا" مباشرة دون مشاكل.
هناك حاجة إلى OOP عندما يكون مشروع كبير هو مشكلة "البيروقراطية" ....
ولكن بالعودة إلى النقطة الرئيسية. في OOP الحقيقي ، هناك SYNTAX SUGAR. المثال أعلاه باستخدام Y_all الهياكل فقط ، سيتم اعتبار الوظائف f (،،،) ثابتة. OOP عبارة عن مجموعة من السكر عندما يبدأ الرمز بالشكل التالي:
Y_all.f1(X1); % Y_all=f1(Y_all, X1),
Y_all.f2(X2);
….
Y_all.f20(X20);
Y_all.DO_MOST_IMPORTANT_SHIT(options_how_to_do_this_shit);
أولئك. لقد قررنا نوعًا ما إحضار صيغة موحلة لا يمكنك فيها كتابة Y_all مرتين ، ولكن عليك القيام بذلك مرة واحدة فقط. لأن التكرار أم التأتأة.
يتلخص باقي شرح "كيفية عمل OOP" في شرح كيفية عمل السكر النحوي.
كيف يعمل السكر النحوي OOP
أولاً ، من الواضح أن قاعدة البيانات Y_all هذه يجب إنشاؤها قبل أن تتحول كوسيطة للوظيفة. هذا يتطلب منشئ.
ثانيًا ، يُنصح بالتنبؤ ، ويفضل مقدمًا ، ما هي "المقصورات" التي ستحتوي عليها. طالما أن قاعدة بيانات Y_all صغيرة ، فإن هذا الإعداد مزعج. أود أن أحلم بـ "الفصول التي تم إنشاؤها أثناء التنقل" ، كما هو الحال في MATLAB ، يمكنك إنشاء هياكل بأوامر بسيطة Ya = 5 ، Yb = 10 . لكن الرغبة في التخيل حول هذا الموضوع تختفي بعد تصحيح أخطاء مشروع سليم.
التالي - استدعاء الطريقة (الوظيفة).
هذه هي الطريقة التي تطورت بها تقريبًا
| وظيفة | تعليق |
|---|---|
| ص = و (س) | كان هذا هو الحال في الرياضيات عندما قمنا بتخطيط بارابول بالنقاط! |
| X = و (X) | لقد تعرضنا للتخويف من قبل البيروقراطيين ، ولدينا |
| و (X) | لماذا يجب أن ترجع الدالة وسيطة؟ هذه هي عفا عليها الزمن في زمن دروس الرياضيات! وإهدار لا طائل منه للذاكرة! دع البيانات يتم تمريرها عن طريق المرجع ، ثم ستأتي الوظيفة نفسها إلى الحجة وتتغير وتترك. لا شيء = و (X)
لا يذهب الجبل إلى محمد ، بل يذهب محمد إلى الجبل. |
| X.f () | لقد سحبنا للتو حجة X باستخدام السكر النحوي. لا شيء = X.f (لا شيء) |
الآن - كيف يتم ترتيب هذه الوظيفة داخليًا بحيث لا تأخذ شيئًا وتعيد أي شيء (الكلمة الأساسية الفارغة في C #).
أحب كيف يتم ذلك في matlab (من وجهة نظر الفهم): الوظيفة التي نسميها باسم Xf () مكتوبة داخليًا
| عينة كود MATLAB | نموذج C # كود |
|---|---|
|
|
| « » . — ( , this, fuck, shit).
this, . |
« » . , ( )!
! , « this». «» this ( ). |
هنا وظيفة مع "الوسيطة الافتراضية هي هذه " ، الكذب في الفصل ، كما هو الحال في مجلد - هناك طريقة عادية (xs ، كما هو صحيح باللغة الروسية).
في الواقع ، ليس من الصحيح دائمًا دفع كل الحجج في هذا واحد . تحتاج أحيانًا إلى بعض الوسائط الأخرى (على سبيل المثال ، هذا إدخال المستخدم):
public void f(int user_input) {
this.c=this.a+this.b + user_input;
}
في بعض الأحيان تحتاج إلى إعادة جدال (على سبيل المثال ، حول نجاح أو فشل عملية ما) ، وعدم كتابة الفراغ . والذي ، مع ذلك ، لا يغير الإحصائيات: معظم دالات OOP ترجع لا شيء ( باطل ) وتقبل إما لا شيء (الوسيطة الافتراضية لا تحسب) أو القليل جدا من الوسائط.
لنكتب الكود النهائي
في MATLAB
classdef MyClass<handle % handle
properties %
a
b
end
methods %
function this=MyClass(a, b) % . a, b -
this.a=a
this.b=b
end
function f(this)
this.c=this.a+this.b
end
end
end
% - Untitled.m
X=MyClass(5,10);
X.f();
fprintf(‘X.c=%d',X.c) % .=15
الآن في C #:
public class MyClass {
public int a;
public int b;
public MyClass(int a, int b) { // . a, b - ()
this.a=a;
this.b=b;
}
public void f(this) {
this.c=this.a+this.b
}
}
// -
MyClass X=new MyClass(5,10);
X.f();
Console.WriteLine(“X.c={0}”,X.c); // .=15
عندما اكتشفت ذلك ، بدا لي أن معظم مشاكل كتابة الكود قد تلاشت في الخلفية ...
الخصائص مقابل الحقول
لنلقي نظرة على مثال.
| بدون خصائص | مع الخصائص |
|---|---|
|
|
|
|
| تعليق:
يمكن استدعاء الوسيطة Set_a مهما كان Set_a (int YourVarName) |
تعليق: المتغير الموجود داخل
المجموعة {...} يجب أن يسمى القيمة دائمًا |
هذا الشيء مناسب تمامًا وغالبًا ما يستخدم ، لكنه لا يزال SYNTAX SUGAR.
الحقل متغير مؤهل بالكامل. الخاصية هي طريقتان من الفئات (get and set) ، صيغة الاستدعاء التي تنسخ "استدعاء متغير".
في الواقع ، يمكنك القيام بما يلي:
int A {
get{ return 0;}
set{ Console.WriteLine(""); }
}
لذلك ، يبدو أنه من المستحسن كتابة خصائص الاسم بحرف كبير والحقول بحرف صغير.
يحدث (على سبيل المثال ، لا يمكنك إنشاء حقل في الواجهات) التي تحتاج إلى القيام بها بسرعة ، ثم يمكنك:
int A { get; set;} // , - _a
// set get .
public int B { get; private set;} //
//( , )
الوراثة ، التغليف ، تعدد الأشكال
لماذا لم تذكرهم من قبل؟ لأنهعندما تكون هناك عملية إتقان مهارات الكتابة بأسلوب OOP
- في الواقع ، عند كتابة الكود ، لا يطلب منهم بهذه القوة كما هو مذكور في الاستعلام "Ok Google ، ما هو OOP". أود أن أقول حتى في البداية إنهم غير ضروريين عمليا .
- حيثما تكون هناك حاجة إليها ، يمكنك أن تقرأ عنها (فقط الكسول لم يكتب عن هذه الحالة).
- سيكون لديك معظم الفصول دون وراثة. أنت تكتب فقط كل الوظائف في الفصل المطلوب ، ولا تحتاج حقًا إلى وراثة شيء ما.بعد ذلك سترتفع يديك إلى كتفيك ، وستكتشف ذلك بنفسك ، بدون هذه المقالة ، حيث لا يجب عليك القيام بذلك ، خاصةً عندما لا تكتب علنًا.
- وفقًا لذلك ، فإن تعدد الأشكال (محلول الميراث) يمر أيضًا عبر الغابة
- سيتم تقليل "التغليف" إلى تخصيص الجمهور في كل مكان (لجميع المجالات والخصائص والطرق).
ولكن لا يزال لمحة
ميراث. هذا نسخ ولصق ذكي
يبدو التنفيذ المعيب لـ "الميراث" كما يلي:
أوه ، الكود الخاص بي يحتوي على فئة تسمى MyClass ، ويفتقد حقل SHIT آخر وطريقة DO_THE_SHIT () أخرى!ما زلنا أكثر تحضرا ، ونعلم أنه من الأفضل عدم نسخ نص البرنامج ، ولكن الرجوع إليه.
* Ctrl + C ، Ctrl + V
* يتم إنشاء فئة جديدة MyClass_s_fichami ويتم إضافة المطلوب هناك
لنفترض أننا ما زلنا نكتب بلغة برمجة قديمة أو لا ندرك شيئًا مثل "الميراث". ثم نكتب فصلين مختلفين
|
|
|
|
ما فعلناه عن الحق هو الميراث. فقط في لغات البرمجة العادية يتم ذلك بأمر واحد:
public class MyClassB : MyClassA {
// MyClassA ,
// base
// a (, , property a) ,
// (. )
public int b;
public void F2(int x){ //
this.b=this.a*this.b;
}
public MyClassB(int a, int b){ //
// base A
//
this.a=a;
this.b=b;
}
}
يعمل الرمز "خارجًا" بنفس الطريقة تمامًا كما في الخيار 2. أي. الكائن ، كما كان ، يصبح "matryoshka" - داخل كائن ما ، يجلس كائن آخر بغباء ، وهناك "قنوات اتصال" ، يمكنك من خلالها الرجوع إلى الكائن الداخلي مباشرة.
رأس سبويلر
في matlab ، الوضع أكثر إثارة للاهتمام إلى حد ما. عند تشغيل المُنشئ الفرعي ، MyClassB ، لا توجد مكالمة هادئة إلى مُنشئ السلف MyClassA .
تحتاج إلى إنشائه مباشرة. من ناحية ، هذا أمر مزعج:
classdef MyClassB<MyClassA
% ...
function MyClassB(a, b)
this@MyClassA(a); % , «»
this.b=b;
end
end
ولكن إذا تم استدعاء التابع مع وسيطات أخرى على الإطلاق ، مثل MyClassB (d) ، فيمكنك إجراء تحويل في الداخل ، شيء مثل:
classdef MyClassB<MyClassA
% ...
function MyClassB(d)
a=d-5;
this@MyClassA(a);
this.b=d+10;
end
end
في C # ، لا يمكن القيام بذلك مباشرة ، وهذا يؤدي إلى الحاجة إلى كتابة نوع من "وظائف التحويل":
class MyClassB:MyClassA{
//...
static int TransformArgs( int d) {return d-5;}
MyClassB(int d):base(TransformArgs(d)) {this.b=d+10;}
}
أو افعل "المنشئات الثابتة" مثل هذا:
class MyClassB:MyClassA {
//...
MyClassB(){} //
static MyClassB GetMyClassB(int d) {
var X=new MyClassB(); //
//
.a=d-5;
.b=d+10;
return X;
}
}
يبدو عن الميراث ، في الأساس كل شيء.
وبطبيعة الحال، لا أحد القوى وريث لكتابة " F1 " طريقة و " في " الملكية بحيث يتم ترجمتها بالضرورة إلى دعوة طريقة السلف والمجالات. البث هو مجرد سلوك "وراثي" افتراضي. يمكنك (بالطبع! هذه طرق أخرى في فصل دراسي آخر ، يا أخي) أن تكتب مثل هذا:
public class MyClassB : MyClassA {
public int a{ //
get { return 0; }
set { base.a=0; }// this.fieldA.a=0;
}
public int b;
public void F1(int x){ // «»
// - base -
Console.WriteLine(“”);//
}
}
التغليف
... من الناحية المفاهيمية ، هذا يعني أنه داخل كائن من الفئة MyClassB في الحقل الأساسي يجلس كائن من الفئة MyClassA ، مع القدرة على بث أوامر التحكم في الخارج. كل هذا مكتوب أعلاه ولا معنى للتكرار.
يوجد مثل هذا الموضوع بمعدلات وصول مختلفة - عامة ، خاصة ، محمية ... حولها ، ما هو أكثر إثارة للاهتمام ، هو مكتوب في كل مكان بشكل طبيعي أو أقل ، أوصي فقط بالقراءة عنه.
الجمهور - وهذا يعني أن المجال ، الملكية أو طريقة سوف تكون مرئية من الخارج ويمكن انسحبت.إذا كنت لا تعرف ماذا تفعل ، فاكتب للجمهور (نصيحة سيئة ، نعم).
ثم تجد القوة في نفسك والتخلص من هذا الجمهور (أو من أجل الوضوح، والاستعاضة عنها القطاع الخاص ) أينما كان غير ضروري (القيام ب "إعادة بيع ديون"). نعم ، بالطبع ، من الجيد جدًا أن تكون صاحب رؤية ،
خاصة - وهذا يعني أن المجال ، الملكية أو طريقة لكائن مجلد ملف مرئيا فقط من داخل الأساليب من هذه الفئة.ولكن ... إنها فئة وليست مثيلة (كائن). إذا كان لديك رمز مثل:
class MyClassA{
private int a=10;
public void DO_SOMETHING(MyClassA other_obj) {
// DO_SOMETHING
// private MyClassA.
this.a=100; //
other_obj.a=100; //
}
}
var X=new MyClassA();
var Y=new MyClassA();
X.DO_SOMETHING(Y); // X.a=100, Y.a=100
يستخدم مثل هذا الشيء في الاستنساخ (انظر مصادر أخرى لمزيد من التفاصيل).
حاولت التفكير في هذا الترتيب من العام و الخاص عند كتابة التعليمات البرمجية . هذا رمز مستهلك للوقت بشكل غير مقبول عند إخراج الكود. ثم اتضح أن الكود نفسه يحتاج إلى أن يتم بطريقة مختلفة اختلافًا جوهريًا.
إذا تم كتابة التعليمات البرمجية في منفردا، فإنه لا معنى لعناء مع القطاع الخاص و العام في وقت مبكر، هناك مهام أكثر أهمية، على سبيل المثال، تأتي في الواقع حتى مع وكتابة التعليمات البرمجية ...
المكان الوحيد الذي هو أكثر أو أقل وضوحا في مكان ما لوضع الخاصة والعامة هي نفسها سيئة السمعة التي تشير إلى نوع من الحقول.
class MyClassA{
// private
private int a; //"private" C# .
// public
public int A {get{...;} set{...;}} // ""
}
في أماكن أخرى ، للترتيب العام والخاص ، تحتاج إلى النظر حقًا إلى ما يقوم به البرنامج ، وعلى الأرجح لن يجدي تعلم ذلك "غائبًا".
محمية - يعني " الجمهور " لجميع أساليب الفئات المشتقة و " الخاص " على كل شيء آخر.بشكل عام ، من المنطقي أن نفترض أن الفئات الموروثة تظهر ببساطة على أنها "نسخ أكثر تطورًا" من أسلافها.
بصراحة ، لقد نسيت بالفعل المكان الذي طبقت فيه هذه الحماية بشكل صريح. عادة إما عامة أو خاصة. معظم الفصول التي كتبتها لم ترث من أي فئات مخصصة أخرى ، وحيثما فعلوا ذلك ، نادرًا ما كانت هناك حاجة ماسة لمثل هذه الأشياء.
الانطباع هو أن المُعدِّلات غير العامة مطلوبة عند العمل في مشروع كبير ، والذي قد يكون مدعومًا من قبل مجموعة من الأشخاص ... ولا يظهر فهم مكان تطبيقها إلا بعد وقت طويل من الالتزام برمز طوله كيلومتر. عند التعلم "بالمراسلة" يصعب بطريقة ما إعطاء هذا الفهم.
تعدد الأشكال
عندما كنت أكتب في Matlab ، لم أستطع أن أفهم سبب الحاجة إلى تعدد الأشكال على الإطلاق وما هو.
بعد ذلك ، عندما قمت بالتبديل إلى C # ، أدركت أن هذه سمة من سمات اللغات النموذجية بشدة ، ولها علاقة ضعيفة جدًا بـ OOP. في matlab ، يمكنك الكتابة في كل مكان دون معرفة وجود تعدد الأشكال - لا توجد كتابة صارمة.
للتبسيط ، دع الفصول تسمى A و B
class A{...}
class B:A{...}
A X=new B();
// x A, - B.
// .
B x_asB=new B();
A x_asA=(A) x_asB;
هذا يسمى التلبيس. في C # ، يمكنك أن تكتب بنفسك (إذا كنت تعرف كيف) أن تكتب أنظمة الصب من النوع المخصص ذاتيًا ، من أي نوع تقريبًا لأي نوع آخر.
هنا - فقط "إخراج" من الصندوق. نظرًا لأن كائنًا آخر من الفئة A يجلس داخل كائن x ينتمي إلى الفئة B ، فإن إحدى طرق الصب الواضحة هي إغلاق جميع الاتصالات من كائن خارجي إلى كائن داخلي. هذا ليس ضروريًا حقًا ، لكن أولئك الذين اخترعوا "تعدد الأشكال" قرروا أنه سيكون أكثر وضوحًا للقيام بذلك. وسيكتب المستخدم باقي الخيارات بنفسه. نأسف على "politota" (الذي لم يعد مناسبًا تمامًا) لعينة 2008-2012.
lass {...}
class : {...}
= new Me (); //
= () ; //
واجهه المستخدم
يجب أن نبدأ بكيفية تطبيق هذا.
لنفترض أن لدينا قائمة ونريد وضع شيء فيها.
في matlab ، أسهل طريقة للقيام بذلك هي (تسمى مصفوفة الخلايا):
myList={1, ‘2’, ‘fuck’, ‘shit’, MyClassA(), MyClassB(), …. ,_, _};
أنت لا تفكر في نوع الكائن ، فأنت تأخذه فقط وتضعه في القائمة.
بعد ذلك ، لنفترض أنك بحاجة إلى تكرار القائمة والقيام بشيء ما مع كل عنصر:
for i=1:length(myList)
item=myList(i);
% - item-
DoSomeStuff(item);
end
إذا كانت وظيفة DoSomeStuff ذكية بما يكفي لاستيعاب كل ما يتم تغذيته بها ، فسيتم ملء هذا الرمز.
إذا كانت وظيفة DoSomeStuff (أو مؤلفها) لا تتألق بالذكاء ، فهناك احتمال أن تختنق بشيء ما: رقم أو سطر أو فئة عصامية أو الشيطان الأصلع أو جدتك - لا قدر الله.
ستعرض MATLAB الشتائم الحمراء باللغة الإنجليزية في وحدة التحكم وتنهي برنامجك. وبالتالي ، سيحصل شفرتك تلقائيًا على جائزة داروين.
ومع ذلك ، هذا أمر سيء في الواقع لأنه في بعض الأحيان يكون الرمز معقدًا للغاية. عندها ستقتنع تمامًا بأنك فعلت كل شيء بشكل صحيح ، ولكن في الواقع ، لم يتم إطلاق المجموعة الخاطئة من الإجراءات ببساطة أثناء الاختبار.
هذا هو السبب (على الرغم من أنه ليس فقط) في MATLAB - تمكنت من التأكد من هذا بنفسي (تقريبًا كما في KPDV) ، من الحجم الرهيب للرمز - ليست هناك حاجة لكتابة مشاريع كبيرة.
الآن دعنا ننتقل إلى C #. نقوم بعمل قائمة ، و ... ويطلب منا الإشارة على الفور إلى نوع الكائن. نقوم بإنشاء قائمة نوع قائمة.
في هذه القائمة يمكنك وضع الرقم 1.
في هذه القائمة يمكنك وضع الرقم 2 وحتى ، سامحني الله ، 3.
List<int> lst1=new List<int>().
lst.Add(1);
lst.Add(2);
lst.Add(3);
لكن السلاسل النصية لم تعد موجودة. كائنات من صفك العصامي - لا تمامًا. أنا صامت بشأن الشيطان الأصلع وجدتك ، لا يمكن أن يكونوا هناك تحت أي بديل.
يمكنك عمل قائمة منفصلة من الأسطر. يمكنك - لدروس عصامية.
List<MyClassA> lst2=new List<MyClassA>();
lst2.Add(new MyClassA());
في الواقع ، يمكنك عمل قوائم - منفصلة - للشياطين الأصلع ، جداتك.
لكن إضافتها إلى قائمة واحدة لن تنجح. سيفوز شفرتك بجائزة داروين ، بالإضافة إلى إساءة استخدام المترجم قبل أن تحاول تشغيله. لا يسمح المترجم بحكمة بعمل وظيفة DoSomeStuff (عنصر) ، والتي سوف "تختنق" بحجتها .
هذا مفيد حقًا في المشاريع الكبيرة.
ولكن ماذا تفعل عندما لا تزال تريد وضعها في قائمة واحدة صغيرة؟
هذه ليست مشكلة حقا. يكفي تحويل كل شيء لكتابة الكائن . يمكن تحويل كل شيء تقريبًا (أو حتى مطلقًا) إلى كائن كتابة .
List<object> lst=new List<object>();
lst.Add((object) new MyClassA());
lst.Add((object) new MyClassB());
تبدأ المشكلة عندما نبدأ في التكرار من خلال القائمة. النقطة المهمة هي أن نوع الكائن (تقريبًا) لا يمكنه فعل أي شيء. يمكن أن يكون فقط من نوع كائن .
- ما الذي تستطيع القيام به؟
- يمكنني الغناء والرقص
- وأنا - سانشو ...
- ماذا يمكنك أن تفعل ، سانشو؟
- أنا سانشو.
- حسنًا ، هل يمكنك فعل أي شيء؟
- أنت لا تفهم. يمكنني أن أكون سانشو.
لذلك ، الواجهة مكتوبة. هذه هي الفئة التي تريد أن ترث منها. تحتوي الواجهة على رؤوس الأسلوب والخصائص.
في حالتنا ، هذه هي الطرق والخصائص التي تضمن التشغيل العادي لوظيفة DoSomeStuff (عنصر) . الواجهة لا تنفذ الخصائص نفسها. يتم ذلك عن قصد. في الواقع ، يمكن للمرء ببساطة أن يرث من بعض الفئات التي يمكن استخدامها بواسطة وظيفة DoSomeStuff () . لكن هذا يعني رمزًا إضافيًا ومبرمجًا نسيًا.
لذلك ، إذا ورث زميل مبرمج من واجهة ، لكنه نسي تنفيذ الخصائص والأساليب الضرورية لفئة ما ، فسيقوم المترجم بكتابتها في الكود باستخدام جائزة داروين. وبالتالي ، يمكنك القيام بذلك:
interface ICanDoTheStuff {...};
class MyClassA: ICanDoTheStuff {…}
class MyClassB: ICanDoTheStuff {…}
static void DoSomeStuff(ICanDoTheStuff item) {…}
List<ICanDoTheStuff> lst= new List<ICanDoTheStuff>();
lst.Add(new MyClassA());
lst.Add(new MyClassB());
for (int i=0; i<lst.Count; i++) {
ICanDoTheStuff item=myList[i];
DoSomeStuff(item);
}
أولئك. التي ، في النهاية ، هناك حاجة إلى واجهة - من أجل إنشاء قائمة مطبوعة ، أو بعض الحقول في الفصل ، وتجاوز الحظر على إضافة (إلى القائمة أو الحقل) بعض القمامة المتبقية هناك.
الواجهة هي "البيروقراطية". ليس في كل مكان وليس في كل مكان مطلوب ، على الرغم من نعم ، فهو ضروري ومفيد في المشاريع الكبيرة.
... بشكل عام ، شيء من هذا القبيل ... أعتذر عن التعبيرات القاسية ، لسبب ما يبدو لي أن العرض "الجاف" للمادة لن ينجح ...