الأصناف في لغة البرمجة Ruby


thaer mohamad

تستخدم الأصناف في البرمجة الغرضية التوجيه من أجل إنشاء الأغراض، وإعطاء القيم الابتدائية للمتغيرات المستنسخة. لكل صنف اسم خاص يعبر عن نوعه ووظيفته.

تعريف الأصناف

جميع الأصناف في Ruby مستنسخة من الصنف الرئيسي Class، حيث يتم تعريف الأصناف في لغة Ruby كما يلي:

  • يبدأ الصنف بالكلمة الدلالية class وبعدها يكتب اسم الصنف.
  • يجب أن يبدأ اسم الصنف بحرف كبير. وفي حال كان اسم الصنف مكون من عدة كلمات، يتم تمييز هذه الكلمات بكتابة أول حرف من كل كلمة بالنمط الكبير وباقي الأحرف صغيرة، كونه لا يمكن استخدام فراغات فاصلة بين الكلمات في أسماء الأصناف.
  • يمكن أن يحتوي الصنف على متغير الصنف، والمتغير المستنسخ، ودالة الصنف، بالإضافة لإمكانية استدعاء الدوال الأخرى مثل الدالة attr_accessor (دوال الولوج).
  • ينتهي الصنف بالكلمة الدلالية end.
    يوضح المثالي التالي طريقة تعريف الأصناف:
class SampleClass
   # some code describing the class behavior  
      def sample_method
   end
end

الاستنساخ

يتم إنشاء الأغراض من الأصناف بعملية تسمى الاستنساخ، حيث يصبح الغرض عبارة عن نسخة من الصنف الذي تم استنساخه عنه. تنفذ عملية الاستنساخ باستخدام الدالة new مع اسم الصنف المراد إنشاء الغرض منه كما هو موضح بالمثال التالي:

std1 = Student.new(parameters)

المتغيرات المستنسخة

وهي المتغيرات التي يتم تعريفها ضمن دوال الأصناف بإضافة الرمز @ لبداية اسم المتغير. وينحصر نطاقها فقط على الغرض المُنشأ من الصنف، ولا يمكن الولوج إليها وإظهار قيمها أو تعديلها إلاّ من خلال الدالة التي عُرّفت فيها (دوال الولوج). سيتم توضيح هذه المتغيرات من خلال المثال التالي:

class Calculation
   @x = 100
   def add_num
      @x = 200
   end
   def show_data
      puts 'Value of x is : '، @x
   end
end

instance = Calculation.new
instance.show_data
instance.add_num
instance.show_data

Output

Value of x is :

Value of x is :
200

نلاحظ أن الخرج الأول الدالة show_data من الغرض instance والمُنشأ من الصنف Calculation فارغ، لأن قيمة المتغير المستنسخ @x مازالت nil (لا شيء) بالرغم من أنه تم إسناد القيمة 100 لهذا المتغير في بداية تعريف الصنف Calculation، وذلك لأن طريقة التعريف هذه خاطئة للمتغير المستنسخ @x، حيث يجب أن يتم تعريفه ضمن دوال الصنف فقط، بالتالي تم تجاهل هذا التعريف. أما الخرج الثاني لهذه الدالة أصبح 200 لأنه تم تنفيذ الدالة add_num (التي عُرّف فيها) من الغرض instance والتي قامت بتهيئة المتغير المستنسخ @x بالقيمة 200.

دوال الولوج

وهي دوال الصنف التي تعرَّف ضمنها المتغيرات المستنسخة، حيث تُستخدم هذه الدال من أجل الولوج إلى المتغيرات المستنسخة للأغراض من أجل قراءة قيمها أو تعديلها. يوضح المثال التالي هذه الدوال:

class MyData
       def set_data(n) 
        @x = n
        end
       def get_data 
          @x
        end
     end

    d =  MyData.new
    puts d.set_data(1000)
    puts d.get_data   

Output

1000
1000

حيث يحتوي الصنف MyData على دالتي ولوج هما: الدالة set_data لتعديل قيمة المتغير المستنسخ @x، والدالة get_data لقراءة قيمة هذا المتغير المستنسخ.

متغيرات الأصناف

وهي المتغيرات المعرفة في بداية الصنف بإضافة الرمز @@ لبداية اسم المتغير، حيث يتم مشاركة قيمها مع جميع الأغراض المُنشأة من هذا الصنف وكذلك مع جميع الأصناف المورَّثة من هذا الصنف، على عكس المتغيرات المستنسخة التي لا يتم مشاركة قيمها بين الأغراض. والمثال التالي يوضح هذه المتغيرات:

class MyData
   @@x = 1
   def add_n
      @@x =  @@x + 10
   end
   def value
      @@x
   end
end
  
ins1 = MyData.new
ins2 = MyData.new
puts ins1.value
ins1.add_n
puts ins1.value
puts ins2.value

Output

1
11
11

المتغيرات المستنسخة للأصناف

تختلف هذه المتغيرات عن متغيرات الأصناف، بأنه يتم مشاركة قيمها مع الأغراض المُنشأة من هذا الصنف فقط، كما هو موضح بالمثال التالي:

class Employee
    class << self; attr_accessor :instances; end
    def store
      self.class.instances ||= []
      self.class.instances << self
    end
    def initialize name
      @name = name
    end
  end
  class Overhead < Employee; end
  class Programmer < Employee; end
  Overhead.new('Martin').store
  Overhead.new('Roy').store
  Programmer.new('Erik').store
  puts Overhead.instances.size    # => 2
  puts Programmer.instances.size  # => 1

Output

2
1

دوال الأصناف

يتم تعريف دوال الأصناف بنفس طريقة تعريف دوال Ruby الاعتيادية باختلاف وحيد، وهو إضافة اسم الصنف أو الكلمة الدلالية self وبعدها نقطة قبل اسم الدالة. يتم استدعاء دوال الأصناف على مستوى الصنف الذي عرفت فيه دون الحاجة لوجود غرض مُنشأ من هذا الصنف. كما يمكن لدوال الأصناف الولوج إلى متغيرات الأصناف لكنها لا تستطيع الولوج إلى المتغيرات المستنسخة (فقط دول الولوج تستطيع ذلك). يوضح المثال التالي كيفية تعريف واستدعاء دوال الأصناف:

class Student
    def self.no_students
      puts 'There are five hundred students in my school.'
    end
  end
  Student.no_students

Output

There are five hundred students in my school.

مستويات الوصول لدوال الأصناف

هنالك ثلاث مستويات للوصول إلى دوال الأصناف هي:

  • الدوال العامة: إن دوال الأصناف في Ruby هي دوال عامة بشكل افتراضي، أي يمكن لأي أحد الوصول إليها، وتشكل واجهة التخاطب للأصناف، حيث يتم من خلالها تبادل المعطيات بين الصنف والعالم الخارجي.
  • الدوال الخاصة: يتم تحديدها بالكلمة الدلالية private، وهي للاستخدام الداخلي فقط ضمن الصنف (يمكن استدعائها خارجياً عن طريق دالة عامة تحوي على هذه الدالة الخاصة مثل whisper_louder)، حيث يمكن الوصول إليها واستخدامها فقط من قبل الدوال الموجودة ضمن تعريف الصنف نفسه أو الأصناف المورَّثة منه، بشرط أن يكون استدعائها صريح (مثل whisper) دون أن تكون مضمّنة في غرض آخر حتى ولو كان من نفس الصنف (مثل self.whisper). عند الرغبة باستدعاء هذه الدوال خارج الصنف عن طريق استدعائها بشكل مضمّن في الدوال العامة كما هو موضح بالمثال التالي:
class Person
   def speak
      puts "Hey، Tj!"
   end
   def whisper_louder
      whisper
   end 
   def whisper_louder_with_self
      self.whisper
   end
# private methods are for internal usage within the defining class
   private 
   def whisper
      puts "His name's not really 'Tj'." 
   end 
end
a_hater = Person.new
a_hater.speak # استدعاء دالة عامة
a_hater.whisper # استدعاء دالة خاصة خارج الصنف
a_hater.whisper_louder # استدعاء دالة عامة تحوي على دالة خاصة صريحة
a_hater. whisper_louder_with_self 
#   استدعاء دالة عامة تحوي على دالة خاصة مضمنة

Output

"Hey، Tj!"
NoMethodError
"His name's not really 'Tj'." 
NoMethodError
  • الدوال المحمية: ويتم تحديدها بالكلمة الدلالية protected، وهي نفس الدوال الخاصة بفارق أساسي هو إمكانية استدعائها داخليا بشكل مضمّن في غرض من نفس الصنف كما هو موضح بالمثال التالي:
class User
   def say_secret_with_self
      self.secret
   end
   protected
   def secret
      "secret"
   end
end

u = User.new
u.say_secret_with_self # => استدعاء دالة عامة تحوي على دالة محمية مضمنة 

Output

"secret"

دوال القراءة والكتابة الشخصية

تُنشأ المتغيرات المستنسخة لكل غرض مُنشأ من صنف، لتستخدم بشكل أساسي ضمن هذا الغرض، لكنها لا تشبه الدوال الخاصة من حيث اقتصارها على الاستخدام الداخلي. حيث يمكن إظهار وتعديل قيمها من خارج الغرض، وذلك عن طريق تعريف دوال القراءة والكتابة الشخصية (مشابه لدوال الولوج). يوضّح المثال التالي طريقة تعريف دالة القراءة (student_name) التي تقوم بقراءة قيمة المتغير المستنسخ:

class Student
   def initialize(student_name، id)
      @student_name = student_name
      @id = id
   end
   def student_name
      @student_name
   end
end

std1 = Student.new("Sara"، 5)
puts std1.student_name

Output

Sara 

والمثال التالي يوضّح طريقة تعريف دالة الكتابة (sname=) والتي تقوم بتغيير قيمة المتغيّر المستنسخ:

class Student
   def initialize(sname)
      @sname = sname
   end
   def sname
      @sname
   end
   def sname=(new_name)
      @sname = new_name
      puts @sname
   end
end
  
# you could the access @sname variable as
a = Student.new('Sara')
puts a.sname 
a.sname ='Robin'

Output

Sara
Robin

دوال القراءة والكتابة الافتراضية

يمكن تنفيذ جميع وظائف قراءة وتعديل قيم المتغيرات المستنسخة عن طريق الدوال attr_accessor و attr_reader و attr_writer والموجودة في لغة Ruby بشكل افتراضي، حيث تستخدم الدالة attr_accessor لتنفيذ عمليتي القراءة والكتابة معًا في هذه المتغيرات كما هو موضح بالمثال التالي:

class Student
   def initialize(sname)
      @sname = sname
   end
       attr_accessor :sname
end
  
# attr_accessor generates variable @sname accessor methods automatically:
a = Student.new('Sara')
puts a.sname 
a.sname = 'Robin'
puts a.sname 

Output

Sara
Robin

أما الدالة attr_reader فتستخدم لتنفيذ عملية القراء فقط، والدالة attr_writer فتستخدم لتنفيذ عملية الكتابة فقط كما هو موضّح بالمثال التالي:

class Student
   attr_reader :sname
   attr_writer :sname
end

s1 = Student.new
s2 = Student.new
s1.sname = "Sara"
s2.sname = "Robin"

puts s1.sname
puts s2.sname

Output

Sara
Robin

ثوابت أصناف لغة Ruby

يمكن أن تعرّف الثوابت ضمن الأصناف، لكن يمكن الولوج إليها من خارج الأصناف على خلاف المتغيرات المستنسخة التي تحتاج لدوال خاصة لتنفيذ ذلك، ويوضح المثال التالي طريقة تعريف الثوابت ضمن الأصناف، واستخدامها داخل وخارج الأصناف:

class ConstClass
   Color1='Red'
   Color2='Green'
   Color3='White'
   def show
      puts "#{Color1} #{Color2} #{Color3}"
   end
end
   
puts( ConstClass::Color1)
ConstClass.new.show

Output

Red
Red Green White

الوراثة

وهي العلاقة بين صنفين، حيث يمكن لصنف أن يرث الوظائف والمتغيرات من صنف أعلى منه مرتبة، ويسمى عندها الصنف الموروث بصنف الأب أو الصنف الأساس، ويسمى الصنف الوارث بصنف الابن، هذا ولا تسمح Ruby بالوراثة المتعددة، أي لكل صنف في Ruby صنف أساس واحد. يوضح المثال التالي طريقة توريث جميع الوظائف والمتغيرات الغير خاصة لصنف آخر (صنف الابن):

class Student
   def schooldetails
      puts 'There are 700 students in our school.'
   end
end
class Classfive <  Student  # < means inherit
   def class5
      puts 'There are 75 students in Class V.'
   end
end

instance = Classfive.new
instance.class5
instance.schooldetails

Output

There are 75 students in Class V.
There are 700 students in our school.

حيث تم في هذا المثال توريث الصنف Classfive من الصنف Student.
يستطيع الصنف الابن الولوج إلى دوال الصنف الأب، عن طريق الكلمة الدلالية super، كما هو موضّح بالمثال التالي:

class Student
   def schooldetails
      puts 'There are 700 students in our school.'
   end
end
class Classfive <  Student  # < means inherit
   def schooldetails
      super      
      puts 'There are 75 students in Class V.'
   end
end
instance = Classfive.new
instance.schooldetails 

Output

There are 700 students in our school.
There are 75 students in Class V.

يمكن في الوراثة المتعددة الولوج إلى دوال الصنف الأب باستخدام أسماء بديلة عن طريق الدالة alias، كما هو موضّح بالمثال التالي:

class V
   def ccccc
      "Class V "
   end
end
class VI  < V
   alias vcv ccccc
   def ccccc
      vcv + "VI "
   end
end
class VII <  VI
   def ccccc
      vcv + "VII "
   end
end
puts V.new.ccccc
puts VI.new.ccccc
puts VII.new.ccccc

Output

Class V
Class V VI
Class V VII

حيث تم استخدام الاسم vcv كبدل لاسم الدالة ccccc المعرّفة في الصنف V، ثم تم استخدام هذا الاسم البديل في الأصناف الوارثة كون اسم دوالها هو نفس الاسم الأصلي لدالة الصنف V.

الأصناف الفريدة

تحتوي لغة Ruby على طريقة لتعريف دوال محددة من أجل غرض معين، حيث تسمى هذه الدوال بالدوال الفريدة. فعند القيام بتعريف دوال فريدة في غرض ما، فإن لغة Ruby تقوم تلقائياً بإنشاء صنف جديد لاحتواء هذه الدوال الفريدة فقط، والذي يسمى عندها بالصنف الفريد. ويفيد هذا الصنف عند الرغبة باستدعاء دواله في أقسام مختلفة من التطبيق البرمجي، مثل تأمين الاتصال مع النظام الخارجي أو الولوج لقاعدة البيانات أو غيرها. ويوضح المثال التالي هذه الأصناف:

tutorial1 = String.new
def tutorial1.size
   "Learn Ruby"
End

tutorial2 = String.new  
puts tutorial1.singleton_methods
puts  tutorial2.singleton_methods

Output

Learn Ruby
String
0

حيث تم استخدام الدالة singleton_method للحصول على قائمة أسماء جميع الدوال الفريدة الموجودة في الغرض.هذا ويمكن الولوج إلى صنف الغرض الفريد باستخدام الصيغة التالي:

class << object

كما هو موضح بالمثال التالي:

arra1 = [] 
class << arra1 
   def foo 
      "Hello World!" 
   end
end 
puts arra1.singleton_methods

Output

foo

ترجمة –وبتصرّف- للمقال Ruby Classes

حقوق خلفية الصورة البارزة محفوظة لـ all-free-download.com





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن