खोज…


एक वर्ग को परिभाषित करना

क्लास के समान नाम वाली .m फ़ाइल में classdef का उपयोग करके एक क्लास को परिभाषित किया जा सकता है। फ़ाइल में classdef हो सकता है ... वर्ग विधियों के भीतर उपयोग के लिए end ब्लॉक और स्थानीय फ़ंक्शन।

सबसे सामान्य MATLAB वर्ग परिभाषा में निम्नलिखित संरचना है:

classdef (ClassAttribute = expression, ...) ClassName < ParentClass1 & ParentClass2 & ...

   properties (PropertyAttributes) 
      PropertyName
   end 

   methods (MethodAttributes) 
      function obj = methodName(obj,arg2,...)
         ...
      end
   end

   events (EventAttributes) 
      EventName
   end

   enumeration
      EnumName
   end

end

MATLAB प्रलेखन: वर्ग गुण , संपत्ति विशेषताएँ , विधि विशेषताएँ , घटना विशेषताएँ , गणना कक्षा प्रतिबंध

उदाहरण वर्ग:

कहा जाता है एक वर्ग Car फाइल में परिभाषित किया जा सकता है Car.m के रूप में

classdef Car < handle % handle class so properties persist
    properties
        make
        model
        mileage = 0;
    end

    methods
        function obj = Car(make, model)
            obj.make = make;
            obj.model = model;
        end
        function drive(obj, milesDriven)
            obj.mileage = obj.mileage + milesDriven;
        end
    end
end

ध्यान दें कि कंस्ट्रक्टर कक्षा के समान नाम के साथ एक विधि है। <एक निर्माता ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में एक वर्ग या संरचना का एक विशेष तरीका है जो उस प्रकार के ऑब्जेक्ट को इनिशियलाइज़ करता है। एक कंस्ट्रक्टर एक आवृत्ति विधि है, जिसमें आमतौर पर कक्षा के समान नाम होता है, और इसका उपयोग किसी वस्तु के सदस्यों के मूल्यों को निर्धारित करने के लिए किया जा सकता है, या तो डिफ़ॉल्ट रूप से या उपयोगकर्ता द्वारा परिभाषित मानों के लिए।>

इस वर्ग का एक उदाहरण कंस्ट्रक्टर को कॉल करके बनाया जा सकता है;

>> myCar = Car('Ford', 'Mustang'); //creating an instance of car class 

drive विधि को कॉल करने से माइलेज बढ़ेगा

>> myCar.mileage 
    
    ans = 
            0

>> myCar.drive(450);

>> myCar.mileage
    
   ans = 
            450

मूल्य बनाम हैंडल कक्षाएं

MATLAB में कक्षाएं दो प्रमुख श्रेणियों में विभाजित हैं: मूल्य वर्ग और हैंडल कक्षाएं। प्रमुख अंतर यह है कि जब मूल्य वर्ग के उदाहरण को कॉपी किया जाता है, तो अंतर्निहित डेटा को नए इंस्टेंस पर कॉपी किया जाता है, जबकि हैंडल क्लासेस के लिए नया इंस्टेंस मूल डेटा को इंगित करता है और नए इंस्टेंस में बदलते मान उन्हें मूल में बदलता है। एक वर्ग को handle क्लास से विरासत में मिला एक हैंडल के रूप में परिभाषित किया जा सकता है।

classdef valueClass
    properties
        data
    end
end

तथा

classdef handleClass < handle
    properties
        data
    end
end

फिर

>> v1 = valueClass;
>> v1.data = 5;
>> v2 = v1;
>> v2.data = 7;
>> v1.data
ans =
     5

>> h1 = handleClass;
>> h1.data = 5;
>> h2 = h1;
>> h2.data = 7;
>> h1.data
ans =
     7

कक्षाओं और अमूर्त कक्षाओं से इनहेरिट करना

अस्वीकरण: यहां प्रस्तुत उदाहरण केवल अमूर्त वर्गों और विरासत के उपयोग को दिखाने के उद्देश्य से हैं और जरूरी नहीं कि यह एक व्यावहारिक उपयोग हो। इसके अलावा, MATLAB में बहुरूपता के रूप में कोई चीज नहीं है और इसलिए अमूर्त वर्गों का उपयोग सीमित है। यह उदाहरण यह दिखाना है कि एक वर्ग को किसने बनाया है, दूसरे वर्ग से विरासत में मिला है और एक सामान्य इंटरफ़ेस को परिभाषित करने के लिए एक अमूर्त वर्ग को लागू करता है।

सार कक्षाओं का उपयोग MATLAB में सीमित है, लेकिन यह अभी भी कुछ अवसरों पर उपयोगी हो सकता है।

मान लें कि हम एक संदेश लकड़हारा चाहते हैं। हम नीचे एक के समान एक क्लास बना सकते हैं:

classdef ScreenLogger
    properties(Access=protected)
        scrh;
    end
    
    methods
        function obj = ScreenLogger(screenhandler)
            obj.scrh = screenhandler;
        end
        
        function LogMessage(obj, varargin)
            if ~isempty(varargin)
                varargin{1} = num2str(varargin{1});
                fprintf(obj.scrh, '%s\n', sprintf(varargin{:}));
            end
        end
    end
end

गुण और विधियाँ

संक्षेप में, गुण एक वस्तु की एक स्थिति रखते हैं, जबकि विधियाँ इंटरफ़ेस की तरह होती हैं और वस्तुओं पर क्रियाओं को परिभाषित करती हैं।

प्रॉपर्टी scrh सुरक्षित है। यही कारण है कि इसे एक निर्माता में आरंभीकृत किया जाना चाहिए। इस संपत्ति को एक्सेस करने के लिए अन्य तरीके (गेटर्स) हैं लेकिन यह इस उदाहरण के सामना से बाहर है। गुण और विधियों को एक चर के माध्यम से एक्सेस किया जा सकता है जो किसी विधि या संपत्ति के नाम के बाद डॉट नोटेशन का उपयोग करके किसी ऑब्जेक्ट का संदर्भ रखता है:

mylogger = ScreenLogger(1);                         % OK
mylogger.LogMessage('My %s %d message', 'very', 1); % OK
mylogger.scrh = 2;                                  % ERROR!!! Access denied

गुण और विधियाँ सार्वजनिक, निजी या संरक्षित हो सकती हैं। इस मामले में, संरक्षित का मतलब है कि मैं विरासत में वर्ग से बाहर तक पहुँचने में सक्षम हो scrh लेकिन बाहर से नहीं। डिफ़ॉल्ट रूप से सभी गुण और विधियाँ सार्वजनिक हैं। इसलिए LogMessage() को स्वतंत्र रूप से वर्ग परिभाषा के बाहर उपयोग किया जा सकता है। इसके अलावा LogMessage एक इंटरफ़ेस को परिभाषित करता है जिसका अर्थ है कि हमें तब कॉल करना चाहिए जब हम अपने कस्टम संदेशों को लॉग करने के लिए ऑब्जेक्ट चाहते हैं।

आवेदन

मान लीजिए कि मेरे पास एक स्क्रिप्ट है जहां मैं अपने लकड़हारे का उपयोग करता हूं:

clc;
% ... a code
logger = ScreenLogger(1);
% ... a code
logger.LogMessage('something');
% ... a code
logger.LogMessage('something');
% ... a code
logger.LogMessage('something');
% ... a code
logger.LogMessage('something');

यदि मेरे पास कई स्थान हैं जहां मैं एक ही लकड़हारे का उपयोग करता हूं और फिर इसे कुछ और परिष्कृत करने के लिए बदलना चाहता हूं, जैसे कि एक फ़ाइल में एक संदेश लिखना, मुझे एक और ऑब्जेक्ट बनाना होगा:

classdef DeepLogger
    properties(SetAccess=protected)
        FileName
    end
    methods
        function obj = DeepLogger(filename)
            obj.FileName = filename;
        end
        
        function LogMessage(obj, varargin)
            if ~isempty(varargin)
                varargin{1} = num2str(varargin{1});
                fid = fopen(obj.fullfname, 'a+t');
                fprintf(fid, '%s\n', sprintf(varargin{:}));
                fclose(fid);
            end
        end
    end 
end

और बस एक कोड की एक पंक्ति को इस में बदलें:

clc;
% ... a code
logger = DeepLogger('mymessages.log');

उपरोक्त विधि बस एक फ़ाइल खोलेगी, फ़ाइल के अंत में एक संदेश संलग्न करें और इसे बंद करें। फिलहाल, अपने इंटरफ़ेस के अनुरूप होने के लिए, मुझे याद रखना होगा कि एक विधि का नाम LogMessage() लेकिन यह समान रूप से कुछ और भी हो सकता है। MATLAB अमूर्त वर्गों का उपयोग करके एक ही नाम पर छड़ी करने के लिए विकासशील को मजबूर कर सकता है। मान लें कि हम किसी भी लकड़हारे के लिए एक सामान्य इंटरफ़ेस परिभाषित करते हैं:

classdef MessageLogger
    methods(Abstract=true)
        LogMessage(obj, varargin);
    end
end

अब, यदि ScreenLogger और DeepLogger दोनों को इस वर्ग से विरासत में मिला है, तो LogMessage() परिभाषित नहीं होने पर MATLAB एक त्रुटि उत्पन्न करेगा। अमूर्त कक्षाएं समान कक्षाएं बनाने में मदद करती हैं जो समान इंटरफ़ेस का उपयोग कर सकती हैं।

इस निर्वासन के लिए, मैं थोड़ा अलग बदलाव करूंगा। मैं यह मानकर चल रहा हूं कि दीपलॉगर एक स्क्रीन पर लॉगिंग संदेश और एक ही समय में एक फ़ाइल में दोनों करेगा। क्योंकि ScreenLogger स्क्रीन पर पहले से ही संदेश लॉग करता है, मैं ScreenLoggger से बचने के लिए DeepLogger से DeepLogger को इनहेरिट करने जा रहा हूं। ScreenLogger पहली पंक्ति से अलग नहीं बदलता है:

classdef ScreenLogger < MessageLogger
// the rest of previous code 

हालाँकि, DeepLogger को LogMessage मेथड में और बदलाव की आवश्यकता है:

classdef DeepLogger < MessageLogger & ScreenLogger
    properties(SetAccess=protected)
        FileName
        Path
    end
    methods
        function obj = DeepLogger(screenhandler, filename)
            [path,filen,ext] = fileparts(filename);
            obj.FileName = [filen ext];
            pbj.Path     = pathn;
            obj = obj@ScreenLogger(screenhandler);
        end
        function LogMessage(obj, varargin)
            if ~isempty(varargin)
                varargin{1} = num2str(varargin{1});
                LogMessage@ScreenLogger(obj, varargin{:});
                fid = fopen(obj.fullfname, 'a+t');
                fprintf(fid, '%s\n', sprintf(varargin{:}));
                fclose(fid);
            end
        end
    end
end

सबसे पहले, मैं बस कंस्ट्रक्टर में गुणों को इनिशियलाइज़ करता हूँ। दूसरी बात, क्योंकि यह वर्ग ScreenLogger से विरासत में मिला है ScreenLogger मुझे इस पेरेन्ट ऑब्जेक्ट को भी इनिशियलाइज़ करना है। यह पंक्ति और भी महत्वपूर्ण है क्योंकि ScreenLogger निर्माता को अपनी स्वयं की वस्तु को शुद्ध करने के लिए एक पैरामीटर की आवश्यकता होती है। यह रेखा:

obj = obj@ScreenLogger(screenhandler);

बस कहते हैं, "ScreenLogger के कंस्ट्रक्टर को कॉल करें और इसे स्क्रीन हैंडलर के साथ निष्क्रिय करें"। यहां यह ध्यान देने योग्य है कि मैंने scrh को संरक्षित के रूप में परिभाषित किया है। इसलिए, मैं DeepLogger से इस संपत्ति का समान रूप से उपयोग कर सकता DeepLogger । यदि संपत्ति को निजी के रूप में परिभाषित किया गया था। इसे ठीक करने का एकमात्र तरीका है कंसीलर का उपयोग करना।

एक और बदलाव खंड methods । पुनरावृत्ति से बचने के लिए, मैं एक स्क्रीन पर एक संदेश लॉग करने के लिए एक मूल वर्ग से LogMessage() हूं। अगर मुझे स्क्रीन लॉगिंग में सुधार करने के लिए कुछ भी बदलना पड़ा, तो अब मुझे इसे एक जगह करना होगा। बाकी कोड वही है जो DeepLogger का एक हिस्सा है।

क्योंकि यह वर्ग एक अमूर्त वर्ग से भी प्राप्त होता है MessageLogger मुझे यह सुनिश्चित करना था कि LogMessage() अंदर DeepLogger LogMessage() को भी परिभाषित किया गया है। MessageLogger से इनहेरिट करना यहाँ थोड़ा मुश्किल है। मुझे लगता है कि यह LogMessage फिर से परिभाषित करने के मामलों को अनिवार्य करता है - मेरा अनुमान है।

कोड के संदर्भ में जहां एक लकड़हारा लगाया जाता है, कक्षाओं में एक सामान्य इंटरफ़ेस के लिए धन्यवाद, मैं आराम कर सकता हूं ताकि पूरे कोड में यह एक पंक्ति किसी भी मुद्दे को न बना सके। पहले की तरह ही मैसेज स्क्रीन पर लॉग इन होंगे लेकिन इसके अलावा कोड एक फाइल में ऐसे मैसेज लिख देगा।

clc;
% ... a code
logger = DeepLogger(1, 'mylogfile.log');
% ... a code
logger.LogMessage('something');
% ... a code
logger.LogMessage('something');
% ... a code
logger.LogMessage('something');
% ... a code
logger.LogMessage('something');

मुझे आशा है कि इन उदाहरणों ने कक्षाओं के उपयोग, विरासत के उपयोग और अमूर्त वर्गों के उपयोग के बारे में बताया।


पुनश्च। उपरोक्त समस्या का समाधान कई में से एक है। एक अन्य समाधान, कम जटिल, ScreenLoger को किसी अन्य FileLogger जैसे कि FileLogger आदि का एक घटक बनाने के लिए होगा। ScreenLogger गुणों में से एक में आयोजित किया जाएगा। इसका LogMessage बस LogMessage के LogMessage को कॉल ScreenLogger और एक स्क्रीन पर टेक्स्ट दिखाएगा। मैंने यह दिखाने के लिए अधिक जटिल दृष्टिकोण चुना है कि मैटलैब में कक्षाएं कैसे काम करती हैं। नीचे दिए गए उदाहरण कोड:

classdef DeepLogger < MessageLogger
    properties(SetAccess=protected)
        FileName
        Path
        ScrLogger
    end
    methods
        function obj = DeepLogger(screenhandler, filename)
            [path,filen,ext] = fileparts(filename);
            obj.FileName     = [filen ext];
            obj.Path         = pathn;
            obj.ScrLogger    = ScreenLogger(screenhandler);
        end
        function LogMessage(obj, varargin)
            if ~isempty(varargin)
                varargin{1} = num2str(varargin{1});
                obj.LogMessage(obj.ScrLogger, varargin{:}); % <-------- thechange here
                fid = fopen(obj.fullfname, 'a+t');
                fprintf(fid, '%s\n', sprintf(varargin{:}));
                fclose(fid);
            end
        end
    end
end

कंस्ट्रक्टर्स

एक निर्माणकर्ता एक वर्ग में एक विशेष विधि है जिसे तब कहा जाता है जब किसी वस्तु का एक उदाहरण बनाया जाता है। यह एक नियमित MATLAB फ़ंक्शन है जो इनपुट मापदंडों को स्वीकार करता है लेकिन इसे कुछ नियमों का भी पालन करना चाहिए।

MATLAB एक डिफ़ॉल्ट बनाता है क्योंकि कन्स्ट्रक्टर्स की आवश्यकता नहीं होती है। व्यवहार में, हालांकि, यह एक वस्तु की स्थिति को परिभाषित करने के लिए एक जगह है। उदाहरण के लिए, गुणों को निर्दिष्ट द्वारा प्रतिबंधित किया जा सकता है गुण । फिर, एक निर्माता डिफ़ॉल्ट या उपयोगकर्ता परिभाषित मूल्यों द्वारा ऐसी संपत्तियों को निष्क्रिय कर सकता है जो वास्तव में एक निर्माता के इनपुट मापदंडों द्वारा भेजा जा सकता है।

एक साधारण वर्ग के एक निर्माता को बुलाना

यह एक साधारण वर्ग का Person

classdef Person
    properties
        name
        surname
        address
    end
    
    methods
        function obj = Person(name,surname,address)
            obj.name = name;
            obj.surname = surname;
            obj.address = address;
        end
    end
end

एक कंस्ट्रक्टर का नाम एक वर्ग का नाम है। नतीजतन, कंस्ट्रक्टरों को इसके वर्ग के नाम से पुकारा जाता है। निम्नानुसार एक वर्ग Person बनाया जा सकता है:

>> p = Person('John','Smith','London')
p = 
  Person with properties:

       name: 'John'
    surname: 'Smith'
    address: 'London'

एक बाल वर्ग के एक निर्माता को बुला रहा है

यदि सामान्य गुण या विधियाँ साझा की जाएँ तो कक्षाएं मूल वर्गों से विरासत में प्राप्त की जा सकती हैं। जब एक वर्ग दूसरे से विरासत में मिलता है, तो संभावना है कि एक मूल वर्ग के एक निर्माता को बुलाया जाना चाहिए।

एक क्लास Member को क्लास Person से विरासत में मिला होता है क्योंकि Member क्लास Person की तरह ही प्रॉपर्टीज का इस्तेमाल करता है लेकिन इसकी payment को भी परिभाषा में शामिल करता है।

classdef Member < Person
    properties
        payment
    end

    methods
        function obj = Member(name,surname,address,payment)
            obj = obj@Person(name,surname,address);
            obj.payment = payment;
        end
    end
end

इसी प्रकार वर्ग के Person , इसके निर्माणकर्ता को बुलाकर Member बनाया जाता है:

>> m = Member('Adam','Woodcock','Manchester',20)
m = 
  Member with properties:

    payment: 20
       name: 'Adam'
    surname: 'Woodcock'
    address: 'Manchester'

Person एक निर्माता को तीन इनपुट मापदंडों की आवश्यकता होती है। Member को इस तथ्य का सम्मान करना चाहिए और इसलिए तीन मापदंडों वाले वर्ग Person एक निर्माता को कॉल करना चाहिए। यह लाइन द्वारा पूरा किया गया है:

obj = obj@Person(name,surname,address);

उपरोक्त उदाहरण उस मामले को दिखाता है जब एक बच्चे की कक्षा को अपने मूल वर्ग के लिए जानकारी की आवश्यकता होती है। यही कारण है कि Member एक निर्माता को चार मापदंडों की आवश्यकता होती है: तीन इसके मूल वर्ग के लिए और एक स्वयं के लिए।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow