آموزش #C – بخش دهم | اعضای استاتیک و متد مجازی

متدهای مجازی در #C

پس از یک آموزش نه‌چندان‌کوتاه در مبحث شی‌گرایی در این بخش از آموزش سی‌شارپ می‌خواهیم در مورد اعضای استاتیک و متدها (شامل متد مجازی و متد پنهان) بحث کنیم. گاهی اوقات برای انجام کاری در کلاس لازم نیست که از آن کلاس شی ایجاد شود چون هم باعث ایجاد سردرگمی و پیچیدگی می‌شود و هم خوانایی برنامه را کم می‌کند. این مشکل را می‌توان با اعضای استاتیک حل نمود. در ارث بری گاهی اوقات متدهای کلاس پایه و مشتق دارای نام و امضای یکسان هستند. در این بخش درباره طرز برخورد با این متدها بحث خواهیم کرد.

اعضای استاتیک (Static)

زبان سی‌شارپ دارای کلمه کلیدی به نام static است که می‌تواند در کلاس‌ها، متدها‌، متغیرها و خواص به کار گرفته شود. اگر کلمه static با کلاس به کار برده شود، با کلمه کلیدی new دیگر نمی‌توان برای آن کلاس شی ساخت. اگر این کلمه با متغیرها ، متدها و خواص به کار رود بدون ایجاد شی می‌توان به آنها دسترسی داشت. دو مثال زیر بیشتر این مفاهیم را روشن می‌کنند.

using System;

namespace ConsoleApp5
{
    static class MyClass
    {
        public static int num1;

        public static int num2;

        public static int Sum()
        {
            return num1 + num2;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass.num1 = 4;
            MyClass.num2 = 7;
            int var = MyClass.Sum();
            Console.WriteLine($"The result of sum is: {var}");
        }
    }
}
The result of sum is:11

همانطور که در مثال بالا مشخص است، کلاس MyClass از نوع static است و باید همه اعضای آن static باشند. به همه‌ی اعضای استاتیک بدون ایجاد شیء و فقط با نام کلاس می‌توان دسترسی پیدا کرد.

using System;

namespace ConsoleApp5
{
    class MyClass
    {
        private static int myStaticVariable = 0;

        public static void myStaticMethod()
        {
            Console.WriteLine("This is static method.");
        }

        public void myNonStaticMethod()
        {
            Console.WriteLine("Non-static method");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass.myStaticMethod();
            MyClass obj = new MyClass();
            obj.myNonStaticMethod();
        }
    }
}
This is static method.
Non-static method

با توجه به کد بالا، کلاس های غیر استاتیک می‌توانند هم دارای اعضای استاتیک باشند و هم نباشند. برای دسترسی به اعضای استاتیک از نام کلاس و برای دسترسی به اعضای غیر استاتیک از شی استفاده کرده‌ایم.

سازنده استاتیک

کلاس‌های استاتیک و غیر استاتیک می‌توانند دارای سازنده استاتیک باشند که هیچگونه سطح دسترسی مثل public ، private و غیره ندارد. سازنده استاتیک در کلاس استاتیک هنگامی اجرا می‌شود که برای اولین بار یک عضو استاتیک اجرا شود. سازنده استاتیک در کلاس غیر استاتیک هنگامی اجرا می‌شود که برای اولین بار یک شیء از این کلاس ایجاد شود. دو مثال زیر بیشتر این مفاهیم را روشن می‌کنند.

using System;

namespace ConsoleApp5
{
    static class MyClass
    {
        public static int Num1 { get; set; }
        public static int Num2 { get; set; }
        static MyClass()
        {
            Console.WriteLine("This is static constructor.");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass.Num1 = 5;
            MyClass.Num2 = 15;
        }
    }
}
This is static constructor.

در مثال بالا از کلاس استاتیک MyClass دو عضو استاتیک را اجرا کردیم و بنابر گفته های قبلی، سازنده استاتیک، فقط هنگام اجرا اولین عضو کلاس اجرا می‌شود.

using System;

namespace ConsoleApp5
{
    class MyClass
    {
        public int Num1 { get; set; }
        public int Num2 { get; set; }
        static MyClass()
        {
            Console.WriteLine("This is static constractor.");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass obj1 = new MyClass();
            MyClass obj2 = new MyClass();
        }
    }
}
This is static constructor.

در مثال بالا از کلاس MyClass دو شی ایجاد کرده‌ایم و بنابر گفته های قبلی، سازنده استاتیک کلاس غیر استاتیک، تنها هنگام ایجاد اولین شی کلاس اجرا می‌شود.

متدهای مجازی

متدهای مجازی متدهایی از کلاس پایه هستند که می‌توان آن‌ها را به صورت دلخواه در کلاس مشتق پیاده‌سازی یا override کرد. به مثال زیر توجه کنید.

using System;

namespace ConsoleApp5
{
    class Parent
    {
        public virtual void Print()
        {
            Console.WriteLine("Method from Parent Class");
        }
    }

    class Child : Parent
    {
        public override void Print()
        {
            Console.WriteLine("Method from Child Class");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Parent parent = new Parent();
            Child child = new Child();

            parent.Print();
            child.Print();
        }
    }
}
Method from Parent Class
Method from Child Class

همانطور که از مثال بالا مشخص است، می‌توان با استفاده از کلمه کلیدی virtual یک متد مجازی در کلاس پایه تعریف کرد. این باعث می‌شود که بتوان با استفاده از کلمه کلیدی override در کلاس مشتق متد مجازی کلاس پایه را طور دیگری پیاده سازی کرد. با ایجاد شی از کلاس مشتق می‌توان به هر دو متد دسترسی پیدا کرد. با کلمه کلیدی base می‌توان متد مجازی کلاس پایه را در هرکجای کلاس مشتق فراخوانی کرد.

base.MethodName();

می‌توان یک کلاس دیگر ایجاد کرد که از کلاس مشتق به ارث می‌برد و متد override کلاس مشتق را بازهم override کند. اگر بخواهیم متد مجازی دیگر override نشود، باید از کلمه کلیدی sealed به صورت زیر استفاده کرد.

public sealed override void Print()
{
    //statement
}

مخفی‌کردن متد (method hiding)

گاهی اوقات یک متد کلاس مشتق دارای نام و امضای شبیه به متد کلاس پایه است. وقتی یک شی از کلاس مشتق ایجاد کنیم و متد را فراخوانی کنیم، متد کلاس مشتق اجرا می‌شود چون که کامپایلر متد کلاس پایه را به صورت خودکار پنهان می‌کند. ولی بهتر است اینکار را خودمان با اضافه‌کردن کلمه کلیدی new در متد کلاس مشتق انجام دهیم.

using System;

namespace ConsoleApp5
{
    class Parent
    {
        public void Print()
        {
            Console.WriteLine("Method from Parent Class");
        }
    }

    class Child : Parent
    {
        public new void Print()
        {
            Console.WriteLine("Method from Child Class");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Parent parent = new Parent();
            Child child = new Child();

            parent.Print();
            child.Print();
        }
    }
}
Method from Parent Class
Method from Child Class

حال اگر بخواهیم از شی کلاس مشتق، متد کلاس پایه را فراخوانی کنیم چند روش برای این مقصود وجود دارد.
الف) متد کلاس پایه را در متد کلاس مشتق با استفاده از کلمه کلیدی base به صورت ()base.Print فراخوانی کنیم.
ب) تبدیل صریح شی کلاس مشتق به کلاس پایه است. ()Parent)child).Print))
ج) دادن ارجاعی از کلاس پایه به شی کلاس مشتق است. ()Parent child = new Child

هر کدام از روش های بالا که پیاده سازی شوند متد کلاس پایه اجرا خواهد شد. حال که با مفاهیم override و hiding آشنا شدیم، بهتر است تفاوت آن‌ها را بدانیم. در override وقتی ارجاعی از کلاس پایه به شی کلاس مشتق بدهیم متد کلاس مشتق اجرا و در hiding متد کلاس پایه اجرا می‌شود.

برای آموزش‌های بیشتر با رزدینو همراه باشید.

یک پاسخ

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *