კვლავ მინდა დავუბრუნდე ობიექტ ორიენტირებული პროგრამირების საწყისების თემას და გავაგრძელო მისი განხილვა ისეთი საკითხით რომლესაც ჰქვია მემკვიდრეობა (Inheritance)



არსებობს 2 სახის მემკვიდრეობა is - a (კლასიკური) და has - a (თანდართვა - დელიგირება). ძირითადად ჩვენ საქმე გვაქვს პირველი სახის მემკვიდრეობასთან, თუმცა ხშირ შემთხვევებში მეორეც არანაკლებ სასარგელოა.
გავერკვეთ იმაში თუ რა არის კლასიკური მემკვიდრეობა და რა შეგვიძლია გავაკეთოთ მისი გამოყენებით. OOP - ს ეს შესაძლებლობა გვაძლევს საშუალებას შევქმნათ კლასები უკვე არსებული კლასების გამოყენებით, ანუ დავირთოთ ძველი კლასების სრული ფუნქციონალობა ახალ კლასში (ხელახალი კოდის წერის გარეშე) და დავაშენოთ ახალი, უფრო გაფართოებული შესაძლებლობები. განვიხილოთ მარტივი მაგალითი: დავუშვათ გვაქვს კლასი "ადამიანი" თვისებებით: სიმაღლე და წონა. ახლა დავუშვათ რომ გვჭირდება შევქმნათ კლასი "მუშა". მუშაც აგრეთვე ადამიანია რომელსაც უნდა ჰქონდეს დამატებითი თვისება "ანაზღაურება". რა თქმა უნდა ჩვენ შეგვიძლია შევქნათ კლასი 3 თვისებით, რაც კონცეპტუალურად არასწორი იქნება, რადგან ჩვენ მოგვიწევს არსებული კოდის ახლიდან გადაწერა, თუმცა კი ფუნქციონალურად ყველაფერი სწორად იმუშავებს, მაგრამ აშკარად უკეთესი გზა არის ის რომ კლასი "მუშა" უნდა იყოს კლასი "ადამიანის" შთამომავალი, ირთავდეს მთლიანად მის ფუნქციონალობას და ჰქონდეს თავისი დამატებითი თვისებები და მეთოდები.
და თუ ჩვენ კიდევ დაგვჭირდა შეგვექმნა კლასები "მძღოლი" და "ტუტორი" რომლებსაც თვისება ანაზღაურების გარდა გააჩნიათ ასევე "სტაჟიც"? ე.ი. გამოჩნა კლასი "მუშას" ორი მემეკვიდრე. ყველაფერი უფრო თვალნათლივ რომ დავინახოთ გადავხედოთ შემდეგ სქემას:

მემვიდრეობა


დამეთანხმებით, რომ ასეთი ლოგიკა გაცილებით გაამარტივებს თქვენი კოდის სტრუქტურას და შეცდომის ალბათობასაც მინიმუმამდე დაიყვას.
უცბათ თუ საჭირო გახდა "ადამიანისათვის" "ეროვნების" თვისების დამატება, ეს ატრიბუტი ემატება მხოლოდ მშობელ კლასს და შესაბამისად "მუშასაც", "მძღოლსაც" და "ტუტორსაც" ავტომატურად დაემატება თვისება "ეროვნება". განვიხილოთ ყოველი ზემოთ თქმული ცოცხალ # - იან მაგალითზე.

public class Human
{
  public int Height { set; get; }
  public int Weight { set; get; }

  public Human()
  { }

  public Human(int Height,int Weight)
  {
    this.Height = Height;
    this.Weight = Weight;
  }
}

public class Worker : Human
{
  public decimal Salary { set; get; }

  public Worker()
  { }

  public Worker(int Height, int Weight, decimal Salary)
    : base(Height, Weight)
  {
    this.Salary = Salary;
  }
}



კლასი Human ორი საკუთარი თვისებით და მისი მემკვიდრე კლასი Worker რომელიც აგრეთვე ირთავს მშობლის ორ თვისებას და გააჩნია საკუთარი ახალი თვისება Salary.
თუ ჩვენ კოდში გამოვაცხადებთ Worker კლასის ახალ ინსტანციას დავინახავთ, რომ მისი მშობილის, Human კლასის თვისებეზე გვექნება ისეთი წვდომა თითქოს ეს თვისებები პირდაპირ Worker კლასში გაგვეწეროს.

მემვიდრეობა


პროგრამირების ენა C# - ში დაშვებულია მხოლოდ ერთეულოვანი მემკვიდრეობა, ანუ არ შეიძლება კლასი Worker იყოს როგორც Human აგრეთვე სხვა რომელიმე კლასის მემკვიდრე. ზოგიერთი სხვა პროგრამირების ენები ამის საშუალებას ჩვენ გვაძლევენ, რასაც ხშირ შემთხვევებში ბევრი გაუგებრობები და შეცდომები მოჰყვება და ზუსტად ამ მიზეზების გამო C# - ის შემქმნელება გადაწვიტეს აეკრძალათ მსგავსი ქმედების ჩადენა.
ჩვენ აგრეთვე შეგვიძლია ავკრძალოთ საკუთარი დაწერილი კლასის მემკვიდრეების შექმნა თუ წინ მივუწერთ მას სიტყვას sealed. ანუ ასეთ შემთხვევაში:

public sealed class Worder : Human
{
 ...
}



ჩვენ აღარ გვექნებოდა საშუალება შეგვექმნა კლასები Drive და Tutor, რომლებიც Worker - ის მემკვიდრეები იქნებოდნენ.

როგორც სტატიის დასაწყისში მოგახსენეთ, რომ არსებობს ორი სახის მემკვირეობა, მოვიდა იმის დრო რომ გაგვეხილა მეორე სახის მემკვიდრეობა.
განვიხილოთ ორი კლასი Ink და Pen (მელანი) და (კალმისტარი). აშკარაა რომ ეს ორი კლასი ურთიერთკავშირშია, მაგრამ კლასიკური მემკვიდრეობის ლოგიკაში არ ჯდება, ამიტომ ჩვენ ვიყენებთ ერთი კლასს მეორეში როგორც თვისებას:

public sealed class Ink
{
  /// <summary>
  /// მოცულობა
  /// </summary>
  public int Volume { set; get; }

  public Ink()
  { }

  public Ink(int Volume)
  {
    this.Volume = Volume;
  }
}

public class Pen
{
  public decimal Price { set; get; }
  public Ink InkObj { set; get; }

  public Pen()
  { }

  public Pen(decimal Price,int Volume)
  {
    this.Price = Price;
    this.InkObj = new Ink();
    this.InkObj.Volume = Volume;
  }
}



მგონი უფრო მარტივია ვიდრე გოგონათ :)
ობიექტ ორიენტირებული პროგრამირების ამ პრინციპების გაგება მეტად მნიშვნელოვანია თქვენი დეველოპერული პროფესიონალიზმის განვითარებისათვის, რადგან მასზე დაყრდნობით არის აგებული ყოველი დიდი Framework რომლებთანაც მოგიწევთ მომავალში მუშაობა.