If you're seeing this message, it means we're having trouble loading external resources on our website.

თუ ვებფილტრს იყენებთ, დარწმუნდით, რომ *.kastatic.org და *.kasandbox.org დომენები არ არის დაბლოკილი.

ძირითადი მასალა

გამეორება: ობიექტზე ორიენტირებული დიზაინი

ეს იმ მასალის შეფასებაა, რომელიც განვიხილეთ ობიექტზე ორიენტირებული დიზაინის ამ გაკვეთილში.
როდესაც პროგრამებს ვქმნით, ხშირად გვინდა სხვადასხვა ობიექტების შექმნა, რომლებიც იზიარებენ გარკვეულ თვისებებს - როგორიცაა კატები, რომელთაც გააჩნიათ ოდნავ განსხვავებული ბეწვის ფერი და ზომა, ან ბევრი ღილაკი სხვადასხვა იარლიყითა და პოზიციით. გვინდა, შეგვეძლოს, ვთქვათ: „აი, ასეთები არიან კატები ზოგადად" და შემდეგ ვთქვათ: „მოდით, შევქმნათ ეს კონკრეტული კატა, აგრეთვე ეს სხვა კატა, ისინი ერთმანეთის მსგავსი იქნებიან გარკვეულწილად, თუმცა რამდენიმე განსხვავებაც ექნებათ." ამ შემთხვევაში გვინდა, გამოვიყენოთ ობიექტზე ორიენტირებული დიზაინი, რათა განვსაზღვროთ ობიექტთა ტიპები და შევქმნათ ამ ობიექტების ახალი ნიმუშები.
იმისათვის, რომ განვსაზღვროთ ობიექტის ტიპი JavaScript-ში, ჩვენ ჯერ უნდა შექმნათ „კონსტრუქტორი ფუნქცია". ეს ის ფუნქციაა, რომელსაც ვიყენებთ, როდესაც გვსურს, შევქმნათ ობიექტის ტიპის ახალი, კერძო სახე. აი, კონსტრუქტორი Book (წიგნის) ობიექტის ტიპისთვის:
var Book = function(title, author, numPages) {
  this.title = title;
  this.author = author;
  this.numPages = numPages;
  this.currentPage = 0;
};
ფუნქცია იღებს არგუმენტებს წიგნების იმ ასპექტებისთვის, რომლებიც განასხვავებენ წიგნებს ერთმანეთისგან - სათაური, ავტორი, გვერდების რაოდენობა. შემდეგ ის საზღვრავს ობიექტის თვისებების საწყის მნიშვნელობებს ამ არგუმენტებზე დაყრდნობით. ამისთვის გამოიყენება საკვანძო სიტყვა this. როდესაც ობიექტში ვიყენებთ this-ს, ჩვენ მივმართავთ ობიექტის მიმდინარე კერძო სახეს საკუთარ თავთან მიმართებაში. ჩვენ იმიტომ გვჭირდება თვისებების this-ის საშუალებით შენახვა, რომ მომავალში შევძლოთ მათი გახსენება.
Book ობიექტის კერძო სახის შესაქმნელად ჩვენ უნდა გამოვაცხადოთ ახალი ცვლადი, რომელშიც შევძლებთ მის შენახვას. შემდეგ უნდა გამოვიყენოთ საკვანძო სიტყვა new, რომლის შემდეგაც უნდა დავწეროთ კონსტრუქტორის ფუნქციის სახელი და გადავცეთ მას კონსტრუქტორისთვის საჭირო არგუმენტები:
var book = new Book("Robot Dreams", "Isaac Asimov", 320);
ჩვენ შეგვიძლია, მივმართოთ ობიექტში შენახულ ნებისმიერ თვისებას წერტილის ნოტაციის გამოყენებით:
println("მომეწონა „ + book.title); // მომეწონა Robot Dreams
println(book.author + „ არის ჩემი საყვარელი მწერალი"); // „ისააკ აზიმოვი" არის ჩემი საყვარელი მწერალი
მოდით, მოვიყვანოთ საპირისპირო, კონტრასტული მაგალითი და ვნახოთ, თუ რა მოხდებოდა კონსტრუქტორის ფუნქცია სწორად რომ არ გაგვემართა:
var Book = function(title, author, numPages) {
};
var book = new Book("Little Brother", „Cory Doctorow", 380);
println("მომეწონა „ + book.title); // მომეწონა undefined (განუსაზღვრელია)
println(book.author + „ არის ჩემი საყვარელი მწერალი"); // undefined (განუსაზღვრელი) არის ჩემი საყვარელი მწერალი
თუ არგუმენტებს კონსტრუქტორის ფუნქციაში გარედან this-ში შენახვის გარეშე გადავცემთ, მოგვიანებით ჩვენ არ გვექნება მათთან წვდომა! ობიექტს დიდი ხნის დავიწყებული ექნება ეს არგუმენტები.
ხშირად ობიექტების ტიპის განსაზღვრისას ჩვენ გვსურს თვისებებისა და ქცევის მათთან დაკავშირება - ზუსტად ისე, როგორც კატის ყველა ჩვენს ობიექტს უნდა შეეძლოს meow() და eat() ფუნქციების შესრულება. შესაბამისად, უნდა შეგვეძლოს, ფუნქციები დავუმატოთ ჩვენი ობიექტის ტიპის განსაზღვრებებს, ამის გაკეთება კი შეგვიძლია მათი ეგრეთ წოდებულ ობიექტის პროტოტიპში განსაზღვრით:
Book.prototype.readItAll = function() {
  this.currentPage = this.numPages;
  println("You read " + this.numPages + " pages!");
};
ეს ძალიან გავს ფუნქციის შექმნის ჩვეულებრივ პროცესს, თუმცა იმ განსხვავებით, რომ ჩვენ გამოვიყენებთ Book-ის პროტოტიპს მისი გლობალურად განსაზღვრის მაგივრად. ზუსტად ასე იგებს JavaScript-ი იმას, რომ ამ ფუნქციის გამოძახება შესაძლებელია ნებისმიერ Book ობიექტზე და ამ ფუნქციას უნდა ჰქონდეს წვდომა იმ წიგნის this-ზე, რომელზეც მოხდა მისი გამოძახება.
ჩვენ შეგვიძლია, გამოვიძახოთ ეს ფუნქცია (რომელსაც მეთოდს ვუწოდებთ, რადგან ის ობიექტზეა მიბმული), ასე:
var book = new Book("Animal Farm", "George Orwell", 112);
book.readItAll(); // თქვენ წაიკითხეთ 112 გვერდი!
გახსოვდეთ, ობიექტზე ორიენტირებული დიზაინის მთავარი აზრი ის არის, რომ გაგვიმარტივოს მრავალი დაკავშირებული ობიექტის (ობიექტის კერძო სახეების) შექმნა. მოდით, ვნახოთ ეს ყველაფერი კოდში:
var pirate = new Book("Pirate Cinema", "Cory Doctorow", 384);
var giver = new Book("The Giver", "Lois Lowry", 179);
var tuck = new Book("Tuck Everlasting", "Natalie Babbit", 144);

pirate.readItAll(); // თქვენ წაიკითხეთ 384 გვერდი!
giver.readItAll(); // თქვენ წაიკითხეთ 179 გვერდი!
tuck.readItAll(); // თქვენ წაიკითხეთ 144 გვერდი!
ეს კოდი გვაძლევს სამ ერთნაირ წიგნს - ყველა მათგანს აქვს ერთნაირი (თუმცა ამავე დროს განსხვავებული) თვისებების ტიპები და ქცევა. შესანიშნავია!
ჩვენს სამყაროზე რომ დაფიქრდეთ, ცხადია, რომ კატები და ძაღლები ობიექტების სხვადასხვა ტიპების წარმომადგენლები არიან, ამიტომ, სავარაუდოდ, სჯობს, შევქმნათ განსხვავებული ობიექტების ტიპები, თუ გვსურს კატის და ძაღლის დაპროგრამება. კატას უნდა შეეძლოს meow() - კნავილი, ხოლო ძაღლს უნდა შეეძლოს bark() - ყეფა. თუმცა ამ ორ ობიექტს შორის არსებობს მსგავსებებიც, ორივეს უნდა შეეძლოს eat() -ჭამა, ორივეს უნდა ჰქონდეს age - ასაკი, birth - დაბადება და death - სიკვდილი. ორივე ძუძუმწოვარია, რაც იმას ნიშნავს, რომ ბევრი საერთო აქვთ იმის მიუხედავად, რომ განსხვავებულნი არიან.
ამ შემთხვევაში ჩვენ უნდა გამოვიყენოთ ობიექტის მემკვიდრეობითობის ცნება. ობიექტის ტიპს შეუძლია მემკვიდრეობით მიიღოს მშობელი ობიექტის ტიპისთვის დამახასიათებელი თვისებები და ქცევები და ამავე დროს ჰქონდეს მხოლოდ მისთვის დამახასიათებელი, უნიკალური ნიშნები. შეგვიძლია, მივუთითოთ, რომ ყველა კატა და ძაღლი ძუძუმწოვრის შვილობილია, რაც იმას ნიშნავს, რომ ჩვენ არ დაგვჭირდება eat() ფუნქციის ორივესთვის ცალკე განსაზღვრა. როგორ გავაკეთოთ ეს ყველაფერი JavaScript-ში?
მოდით, დავუბრუნდეთ ჩვენი წიგნის მაგალითს და ჩავთვალოთ, რომ წიგნი „მშობელი" ობიექტის ტიპია და ჩვენ გვსურს მისი ორი შვილობილი ობიექტის შექმნა. ესენია: Paperback (ქაღალდის წიგნი) და EBook (ელექტრონული წიგნი).
ქაღალდის წიგნი ჩვეულებრივი წიგნივითაა, თუმცა ერთი განსხვავებით (ყოველ შემთხვევაში, ჩვენი პროგრამისთვის): მას აქვს გარეკანის სურათი. შესაბამისად, ჩვენმა კონსტრუქტორმა უნდა მიიღოს ოთხი არგუმენტი, რათა მიიღოს დამატებითი ინფორმაცია:
var PaperBack = function(title, author, numPages, cover) {
  // ...
}
ახლა პირველი სამი არგუმენტის დასამახსოვრებლად ჩვენ უკვე არ გვჭირდება მთელი იმ სამუშაოს შესრულება, რომელიც წიგნის კონსტრუქტორში შევასრულეთ - ჩვენ უნდა ვისარგებლოთ იმ ფაქტით, რომ ამ დავალებისთვის ზუსტად იგივე კოდი გვჭირდება. ამიტომ ჩვენ შეგვიძლია, გამოვიძახოთ Book-ის კონსტრუქტორი PaperBack-ის კონსტრუქტორიდან და გადავცეთ მას ეს არგუმენტები:
var PaperBack = function(title, author, numPages, cover) {
  Book.call(this, title, author, numPages);
  // ...
};
თუმცა ჩვენ ისევ გვჭირდება cover (ყდა) თვისების ობიექტში შენახვა, ამიტომ ამის გასაკეთებლად მოდით, დავამატოთ კიდევ ერთი ხაზი:
var PaperBack = function(title, author, numPages, cover) {
  Book.call(this, title, author, numPages);
  this.cover = cover;
};
ახლა ჩვენ გვაქვს კონსტრუქტორი ჩვენი ქაღალდის წიგნისთვის, რომელიც ანიჭებს მას იგივე თვისებებს, რაც წიგნს აქვს, თუმცა ჩვენ ასევე გვჭირდება, რომ ჩვენს ქაღალდის წიგნს მემკვიდრეობით გადაეცეს მისი მეთოდებიც. ამისთვის ჩვენ უნდა ვუთხრათ პროგრამას, რომ ქაღალდის წიგნის პროტოტიპი უნდა იყოს დაფუძნებული წიგნის პროტოტიპზე:
PaperBack.prototype = Object.create(Book.prototype);
ჩვენ ასევე შესაძლოა, მოგვინდეს ქაღალდის წიგნისთვის დამახასიათებელი ქცევის დამატება, მაგალითად, უნდა გვქონდეს მისი დაწვის საშუალება. ამის გასაკეთებლად ჩვენ უნდა განვუსაზღვროთ პროტოტიპს მეთოდები, ზუსტად ისე, როგორც ეს ზედა ხაზზეა წარმოდგენილი:
PaperBack.prototype.burn = function() {
  println("ვაიმე, თქვენ დაწვით „ + this.numPages + „-ივე გვერდი");
  this.numPages = 0;
};
ახლა ჩვენ შეგვიძლია ახალი ქაღალდის წიგნის შექმნა, მისი წაკითხვა და დაწვა!
var calvin = new PaperBack("The Essential Calvin & Hobbes", "Bill Watterson", 256, "http://ecx.images-amazon.com/images/I/61M41hxr0zL.jpg");

calvin.readItAll(); // თქვენ წაიკითხეთ 256 გვერდი!
calvin.burn(); // ღმერთო ჩემო, თქვენ დაწვით 256-ივე გვერდი!
(ჩვენ ნამდვილად არ ვაპირებთ მის დაწვას, რადგან ეს საოცარი წიგნია, მაგრამ თუ ყინულოვან უდაბნოში დავიკარგეთ და სითბო სასიცოცხლოდ დაგვჭირდა, მაშინ არაფერია გამორიცხული)
და ახლა თქვენ ხედავთ, როგორ შეგვიძლია ობიექტზე ორიენტირებული დიზაინის წესების გამოყენება JavaScript-ში უფრო რთული მონაცემების შესაქმნელად თქვენს პროგრამებში და თქვენი პროგრამის სამყაროს უკეთესად მოდელირებაში.

გსურთ, შეუერთდეთ დისკუსიას?

გესმით ინგლისური? დააწკაპუნეთ აქ და გაეცანით განხილვას ხანის აკადემიის ინგლისურენოვან გვერდზე.