گفتگو هایی در باب سی شارپ

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
virtual به این معنا است که متدی، مشخصه ای، رخدادی و یا اندیس دهنده ای این آمادگی را دارد که در فرزندان اش به شیوه دیگری بازنویسی شود.

سلام آقا علی
ببخشید شما گفتین توی خط بالا که علاوه بر متد ، مشخصه ها هم قابلیت تعریف virtual رو دارن . منظورتون از مشخصه همون متغییر ها هستن؟ اگه آره ، بهم اجازه نمیده که یه متغییر رو از نوع virtual تعریف کنم
منظورتون از اندیس دهنده ها ، آرایه ها و استراکچرها هستن؟
ممنون
 

the_king

مدیرکل انجمن
سلام آقا علی
ببخشید شما گفتین توی خط بالا که علاوه بر متد ، مشخصه ها هم قابلیت تعریف virtual رو دارن . منظورتون از مشخصه همون متغییر ها هستن؟ اگه آره ، بهم اجازه نمیده که یه متغییر رو از نوع virtual تعریف کنم

منظورم از مشخصه Property ئه :
کد:
        public class C : Component
        {
            public override ISite Site
            {
                get
                {
                    return base.Site;
                }
                set
                {
                    base.Site = value;
                }
            }
        }


منظورتون از اندیس دهنده ها ، آرایه ها و استراکچرها هستن؟
ممنون
نه، شما می توانید به یک کلاس این قابلیت رو بدید که نقش یک مجموعه رو ارائه کنه که با اندیس به عضو هاش دسترسی ایجاد بشه، شما []this رو تعریف می کنید و وقتی [] به اشیاء اضافه بشه اشاره به همون []this ئه میشه :

کد:
        private object a, b;

        public object this[int index]
        {
            get
            {
                return (index == 0) ? a : b;
            }
            set
            {
                if (index == 0)
                {
                    a = value;
                }
                else
                {
                    b = value;
                }
            }
        }
کد:
            var x = new Class1();
            x[1] = 20;

دست تون هم در نوع اندیس ها باز ئه :
کد:
        public string this[string firstName, string lastName]
        {
            get
            {
                return firstName + " " + lastName;
            }
        }
کد:
            var x = new Class1();
            var s = x["will", "smith"];
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون آقا علی
والا هنوز به این مباحث property و آرایه و استراکچر و اینا نرسیدم و اینا باشه بعدا
من الان توی کلاسی بنام GrandFather (کلاس پدر) تابع زیر رو تعریف کردم :

کد:
        public virtual string Test1()
        {
            string X = "Class GrandFather Test1 Method Public";
            return X;
        }

و در کلاس Father که فرزند کلاس GrandFather هست ، کد زیر رو :

کد:
        public override string Test1()
        {
            string Y = "New String";
            return base.Test1();
        }

من الان میخام بجای اینکه متغییر X در متد در کلاس GrandFather برگردونده شه ، بجاش اون متغییر Y در متد در کلاس Father برگردونده شه ، باید چی کار کنم؟
 

the_king

مدیرکل انجمن
ممنون آقا علی
والا هنوز به این مباحث property و آرایه و استراکچر و اینا نرسیدم و اینا باشه بعدا
من الان توی کلاسی بنام GrandFather (کلاس پدر) تابع زیر رو تعریف کردم :

من الان میخام بجای اینکه متغییر X در متد در کلاس GrandFather برگردونده شه ، بجاش اون متغییر Y در متد در کلاس Father برگردونده شه ، باید چی کار کنم؟
کد:
        public override string Test1()
        {
            string Y = "New String";
            return [B][COLOR="#0000FF"]Y[/COLOR][/B];
        }
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
کد:
        public override string Test1()
        {
            string Y = "New String";
            return [B][COLOR=#0000FF]Y[/COLOR][/B];
        }

ممنون
یعنی قسمت


کد:
base.Test1()

رو پاک کنم؟
پس اون کسی که آموزش شو میبینم گفته بود به این قسمت کاری نداشته باشین !
کلا این قسمت برای چی هست؟ به این دلیل هست که اگه طرف در قسمت تابع override شده (مثلا در متد در کلاس Father) فراموش کرد یا نخواست چیزی رو در موقع برگردوندن تابع تغییر بده ، تابع مقدار اصلی خودشو برگردونه؟ بنابراین زمانی که ما میخوایم تغییرش بدیم این قسمت رو ، اشکالی نداره حذفش کنیم؟
 

the_king

مدیرکل انجمن
ممنون
یعنی قسمت


کد:
base.Test1()

رو پاک کنم؟
پس اون کسی که آموزش شو میبینم گفته بود به این قسمت کاری نداشته باشین !
کلا این قسمت برای چی هست؟ به این دلیل هست که اگه طرف در قسمت تابع override شده (مثلا در متد در کلاس Father) فراموش کرد یا نخواست چیزی رو در موقع برگردوندن تابع تغییر بده ، تابع مقدار اصلی خودشو برگردونه؟ بنابراین زمانی که ما میخوایم تغییرش بدیم این قسمت رو ، اشکالی نداره حذفش کنیم؟
ممکنه برای دور نشدن از موضوع یک آموزش بشه گفت فعلا یک قسمتی رو نادیده بگیرید اما قطعا یک توصیه دائمی نیست.
وقتی قراره مقداری برگردونده بشه مثلا دارید یک متدی که string بر می گردونه رو override می کنید، حداقل یک return لازمه و نمی توانید return نداشته باشید. اما اینکه چه مقدار برگردونده بشه جزو اساس override کردن نیست.
این ()base.Test1 هم جزو مبانی قضیه نیست، base به شما این امکان رو میده که چیزی رو صریحا از کلاس والد رو بکار ببرید. این روال ویژوال استدیو است که به عنوان پیشفرض کدی بنویسه که از والد متد یا مشخصه رو فراخوانی کنه،
اما صرفا یک انتخاب ئه، حفظ کردنش بستگی به کاربرد شما داره. خیلی عادی ئه که تغییرش دهید یا حذف اش کنید.

فراموش کردن که نه، ولی همانطور که اشاره کردید گاهی قصد تغییر مقدار رو نداریم و صرفا مواردی اضافه میشه یا به جهتی صفات متد یا مشخصه تغییر می کنه، مثلا قراره متدی مخفی بشه یا با هر بار اجرا شدن متد کار اضافه ای هم انجام بشه.
در سایر موارد پاک اش می کنند.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
یا با هر بار اجرا شدن متد کار اضافه ای هم انجام بشه.
در سایر موارد پاک اش می کنند.

واقعا ممنونم ازتون :rose:
یعنی در چند ریختی وقتی مثلا من از هر کلاس دیگه ای ، متد override شده در کلاس Father رو فراخونی میکنم ، علاوه بر اون ، متد اصلی در GrandFather هم اجرا میشه؟
 

the_king

مدیرکل انجمن
واقعا ممنونم ازتون :rose:
یعنی در چند ریختی وقتی مثلا من از هر کلاس دیگه ای ، متد override شده در کلاس Father رو فراخونی میکنم ، علاوه بر اون ، متد اصلی در GrandFather هم اجرا میشه؟
کلا دست برنامه نویس باز ئه که در اینجور موارد تصمیم بگیره. الزاما علاوه بر اون نیست، اگر بخواهید می توانید همچین حالتی رو ایجاد کنید اما به هر حال اگر شما نخواهید متد اصلی GrandFather به هیچ عنوان اجرا نمیشه.
در کل چیزی است که متد Father بروز میده، حالا ممکنه شما متد رو طوری بنویسید که مشابه متد اصلی GrandFather عمل کنه به همراه کار اضافه ای :
کد:
public override string Test1()
{
    string Y = "New String" [B][COLOR="#0000FF"]+ base.Test1()[/COLOR][/B];
    return Y;
}
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون آقا علی
این مرده زیاد روی ارث بری مخصوصا چند ریختی تمرکز نکرد منم هی سئوال برام پیش میاد
:)
آقا ببینین این رو درست میگم درباره الویت اجرای کد در مبحث ارث بری؟ :
وقتی از یک کلاسی ، یه کلاس فرزند رو براش شی درست میکنیم ، اول متغییرهای سراسری کلاس فرزند اجرا میشه و اگه فقط کلاس فرزند متد سازنده داشته باشه ، بدون هیچ دغدقه ای کل متد سازنده ی کلاس فرزند اجرا میشه ولی اگه کلاس پدر هم متد سازنده داشته باشه ، اول هد (پروتوتایپ) متد سازنده کلاس فرزند اجرا میشه ولی بدنه ی متد سازنده ی کلاس فرزند اجرا نمیشه و حالا میره سراغ کلاس پدر و اول متغییرهای سراسری کلاس پدر (متغییرهای سراسری ای که قبل از متد سازنده نوشته شدن) اجرا میشه و بعد در صورت داشتن متد سازنده در کلاس پدر ، متد سازنده اش اجرا میشه و بعد از این هم بازم در صورت داشتن متد سازنده کلاس پدر ، بدنه ی متد سازنده کلاس فرزند اجرا میشه
این ترتیب های اجرای کدها درستن؟
 

the_king

مدیرکل انجمن
ممنون آقا علی
این مرده زیاد روی ارث بری مخصوصا چند ریختی تمرکز نکرد منم هی سئوال برام پیش میاد
:)
آقا ببینین این رو درست میگم درباره الویت اجرای کد در مبحث ارث بری؟ :
وقتی از یک کلاسی ، یه کلاس فرزند رو براش شی درست میکنیم ، اول متغییرهای سراسری کلاس فرزند اجرا میشه و اگه فقط کلاس فرزند متد سازنده داشته باشه ، بدون هیچ دغدقه ای کل متد سازنده ی کلاس فرزند اجرا میشه ولی اگه کلاس پدر هم متد سازنده داشته باشه ، اول هد (پروتوتایپ) متد سازنده کلاس فرزند اجرا میشه ولی بدنه ی متد سازنده ی کلاس فرزند اجرا نمیشه و حالا میره سراغ کلاس پدر و اول متغییرهای سراسری کلاس پدر (متغییرهای سراسری ای که قبل از متد سازنده نوشته شدن) اجرا میشه و بعد در صورت داشتن متد سازنده در کلاس پدر ، متد سازنده اش اجرا میشه و بعد از این هم بازم در صورت داشتن متد سازنده کلاس پدر ، بدنه ی متد سازنده کلاس فرزند اجرا میشه
این ترتیب های اجرای کدها درستن؟

صرف نظر از اینکه یکسری مفاهیم مثل اجرا شدن رو اشتباهی برای مواردی مثل متغیر بکار می برید، تفسیر تون از منطقی که زبان #c برای اجرای متد سازنده بکار می بره تقریبا درسته. اما در نظر بگیرید که پروتوتایپ صرفا
تعریف نام و پارامتر های ورودی و مقدار بازگشتی ئه، قابلیت اجرایی نداره که بخواهد به عنوان یک مرحله از فرایند اجرا بشه. متد سازنده کلاس با توجه به تعداد پارامتر ورودی و نوع داده شون تنوع داره. اگر یک کلاس چندین متد سازنده داشته باشه
دیگه تفسیر ، اینکه کدوم شون اجرا بشه بستگی به کدی داره که برای ساختن کلاس ها بکار برده میشه.

در کل ترتیب مقدار دهی متغیر های سراسری رو از فرزند به سمت والد و ترتیب اجرای متد های سازنده رو از والد به سمت فرزند و اولویت مقدار دهی متغیر های سراسری بر اجرای متد سازنده در نظر بگیرید.

اگر شی ای از کلاس Class2 که فرزند Class1 است ایجاد بشه، اجرا ابتدا از مقدار دهی متغیر های سراسری شروع خواهد شد، اول مقدار دهی متغیر های سراسری کلاس فرزند و سپس متغیر های سراسری کلاس والد.
پس اول پیغام Class4 و سپس پیغام Class3 نمایش داده می شود.
بعد نوبت اجرای متد های سازنده کلاس است، ابتدا متد سازنده کلاس والد و سپس متد سازنده کلاس فرزند.
یعنی در ادامه اول پیغام Class1 و سپس پیغام Class2 نمایش داده می شود.
کد:
    public class Class1
    {
        public Class3 a = new Class3();

        public Class1()
        {
            System.Windows.Forms.MessageBox.Show("Class1");
        }
    }

    public class Class2 : Class1
    {
        public Class4 b = new Class4();

        public Class2()
        {
            System.Windows.Forms.MessageBox.Show("Class2");
        }
    }

    public class Class3
    {
        public Class3()
        {
            System.Windows.Forms.MessageBox.Show("Class3");
        }
    }

    public class Class4
    {
        public Class4()
        {
            System.Windows.Forms.MessageBox.Show("Class4");
        }
    }
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنونم ازتون
قضیه اش پس همونطور که گفتم بود
ولی من چون هنوز به خیلی از قسمت ها نرسیدم و مبتدی هستم بخشی از کدتون یعنی خط سوم برام ناآشنا هست :

کد:
public Class3 a = new Class3();

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

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ببخشید آقا علی کنجکاو شدم بدونم اون کد خط بالا چیه دقیقا؟
اگه سطح دسترسی public که اولش نوشتین رو برداریم میشه همون ساخت شی یعنی اگه این جوری باشه :

کد:
Class3 a = new Class3();

ولی تا جایی که میدونم موقع تعریف شی ، سطح دسترسی براش نمیزارن
چیه دقیقا این؟
--------------
بعد یه سئوال دیگه دارم اینکه داخل یک کلاس میشه کلاس دیگه ای تعریف کرد و بعد داخل اون متد و اعضاء تعریف کرد؟ (منظورم تعریف یک کلاس کنار کلاس دیگه نیست. منظورم داخل یک کلاس هست)
همینطور میشه داخل یک فضای نام ، یک فضای نام جدید تعریف کرد؟ همینطور کنار یک فضای نام ، فضای نام جدید تعریف کنیم چی؟
-------------
چجوری میشه تو کد زیر ، از کلاس داخلی شی درست کرد یا متد meth را فراخونی کرد؟ :

کد:
namespace MultiClassTest
{
    class MyClass1
    {
        public class MyClass2
        {
            public string x = "1";
            public string meth()
            {
                string y = "internal class";
                return y;
            }
        }
    }
}

فضای نام تو در تو رو فهمیدم که باید فضای نام ها را با استفاده از using و نوشتن نام فضای نام و بعد با گذاشتن نقطه و بعد نوشتن فضای نام داخلی ، ملحق کنیم

به این نکته توجه کنید که اگر کلاس B وارث کلاس A باشد و کلاس C وارث کلاس B باشد، C می تواند هر چیزی که
در A ویژگی virtual داشته را override کند، چه در B بازنویسی شده باشند و چه نشده باشند.

منظورتون اینه که اگه A کلاس پدربزرگ و B پدر و C فرزند باشه و مثلا متد Test در کلاس پدربزرگ یعنی کلاس A بصورت virtual تعریف شده باشه و بعد در کلاس B یه override از متد Test بسازیم و این متد رو هر جور دلمون خواست تغییر بدیم و بعد حالا میتونیم توی کلاس C متد Test در کلاس A یعنی کلاس پدربزرگ رو دوباره override کنیم؟!
ولی من اینو تست کردم دیدم وقتی میخوایم یه متد رو override کنیم ، فقط آخرین متدی که override کردیم در آخرین کلاس در دسترسمون هست و فقط اونو میتونیم تغییر بدیم و متدهای دیگه در کلاس های قبلی اش که override کردیم از دسترسمون خارج میشه یعنی وقتی در کلاس B که متد رو یه بار override کردیم (چون در کلاس A بصورت virtual تعریف کردیم) ، در دفعه ی بعد که میخوایم override تعریف کنیم یعنی وقتی در کلاس C بصورت override میخوایم بنویسیم ، فقط متد Test ای که در کلاس B (بصورت override) تعریف کردیم در دسترسمون هست و متد Test در کلاس A از دسترس مون خارج میشه


کلاس B می تواند Test کلاس A را نادیده بگیرد، مثلا می خواهد Test اش private باشد، دقت کنید که override ای در کار نیست،
عبارت new مشخص کننده نادیده گرفتن صریح Test کلاس A است :

کد:
    public class B : A
    {
        private [B][COLOR=#0000ff]new[/COLOR][/B] void Test()
        {
        }
    }


کلاس B می تواند Test جدید اش را طوری ارائه کند که فرزندانش بتوانند آنرا بازنویسی کنند، هم عبارت new و هم virtual بکار رفته.
فرزندان کلاس B ارتباط شان را با Test ئه کلاس A از دست می دهند، چون B از اساس Test جدیدی را virtual کرده :
کد:
    public class B : A
    {
        public [B][COLOR=#0000FF]new virtual[/COLOR][/B] void Test()
        {
        }        
    }

البته موارد زیادی در این بحث چند ریختی هست، مخصوصا یکسری موارد خاص ویژوال استدیو هست، مثلا در بعضی از کلاس ها
بخشی از موارد رو override می کنند، نه به این جهت که باز نویسی شوند، صرفا به این جهت که از دید برنامه نویس مخفی شوند. در فروم از اینجور مثال ها هست.

من این تیکه ها رو متوجه نشدم
وقتی در کلاس پدربزرگ که متدم رو public و virtual تعریف کردم و بعد در کلاس پدر بصورت private new تعریف کردم ، از متد فرزند هم به متد مورد نظر در کلاس پدربزرگ دسترسی داشتم یعنی فرزندان ارتباط شون رو با متد در کلاس پدربزرگ از دست ندادن

------------------------------------------

یه سئوال دیگه اینکه وقتی توی کلاس پدر ، متدی با قابلیت virtual تعریف میکنم توی هیچ متدی از کلاس پسر با کلمه کلیدی this در دسترس نیست و فقط باید شی براش درست کنم تا در دسترس قرار بگیره . سطح دسترسی شم public هه
مگه کلمه کلیدی this هم کلاس خودی و هم کلاس های اجدادش رو اون عضوهایی که قابلیت دسترسی دارن (بجز public static) رو در دسترس مون قرار نمیده؟

 
آخرین ویرایش:

the_king

مدیرکل انجمن
ببخشید آقا علی کنجکاو شدم بدونم اون کد خط بالا چیه دقیقا؟
اگه سطح دسترسی public که اولش نوشتین رو برداریم میشه همون ساخت شی یعنی اگه این جوری باشه :

کد:
Class3 a = new Class3();

ولی تا جایی که میدونم موقع تعریف شی ، سطح دسترسی براش نمیزارن
چیه دقیقا این؟
بصورت پیشفرض متغیر سراسری کلاس private ئه مگر اینکه صریحا مشخص کنید، مثلا x اینجا یک متغیر سراسری private ئه :
کد:
    class Class1
    {
        int x;
    }
و با این فرقی نداره :
کد:
    class Class1
    {
        [B][COLOR="#0000FF"]private[/COLOR][/B] int x;
    }
و متغیر سراسری private از بیرون کلاس دیده نمی شود، حالا چه برای کلاس فرزند و چه سایر محیط ها.

و مقدار اولیه متغیر های سراسری مقدار پیشفرض نوع داده اونها است، مگر اینکه صریحا مقدار دهی شون کنید، مثلا مقدار پیشفرض int ها صفر ئه، پس مشابه این خواهد بود :
کد:
    class Class1
    {
        private int x [B][COLOR="#0000FF"]= 0[/COLOR][/B];
    }

و اینم یه متغیر سراسری private از نوع کلاس Class1 است و مقدار اولیه اش null است، مقدار پیشفرض انواع داده ای که با شیء سر و کار دارند null است :
کد:
    class Class1
    {
        Class3 a;
    }

و این یک متغیر سراسری public از نوع کلاس Class3 است که مقدار اولیه اش یک شیء از همون نوع است :
کد:
    class Class1
    {
        public Class3 a = new Class3();
    }
و متغیر سراسری public از بیرون کلاس قابل مشاهده است، چه فرزند اش باشد و چه نباشد.


بعد یه سئوال دیگه دارم اینکه داخل یک کلاس میشه کلاس دیگه ای تعریف کرد و بعد داخل اون متد و اعضاء تعریف کرد؟ (منظورم تعریف یک کلاس کنار کلاس دیگه نیست. منظورم داخل یک کلاس هست)
همینطور میشه داخل یک فضای نام ، یک فضای نام جدید تعریف کرد؟ همینطور کنار یک فضای نام ، فضای نام جدید تعریف کنیم چی؟
هم namespace و هم class ها ساختار سلسله مراتبی رو می پذیرند، همانطور که if و for و سایر بلوک ها می توانند تو در تو باشند.
می توانید داخل یک کلاس کلاس دیگری و داخل فضای نام ای فضای نام دیگری را تعریف کنید.
در هر دو مورد وقتی داخل هم قرار می گیرند ترکیب شون با نقطه انجام میشه، یعنی اگر نام کامل شون رو بخواهید یک کاراکتر . بین شون قرار می گیره، فرضا اگر کلاس B رو داخل کلاس A تعریف کنید، خارج از کلاس A کلاس B رو با نام A.B می شناسند.
همانطور که اگر فضای نام B رو داخل فضای نام A تعریف کنید، مواردی که داخل B می نویسید در فضای نام A.B قرار دارند.

کد:
    public class Class1
    {
        public class Class3
        {

        }
    }

    public class Class2
    {
        public class Class3
        {

        }
    }

    public class Test
    {
        [B][COLOR="#0000FF"]Class1.Class3[/COLOR][/B] x;
        [B][COLOR="#0000FF"]Class2.Class3[/COLOR][/B] y;
    }
و نکته اینجا است که Class3 با توجه به جایی که به آن اشاره می شود کلاس متفاوتی است، Class1.Class3 و Class2.Class3 دو کلاس کاملا متفاوت اند.


چجوری میشه تو کد زیر ، از کلاس داخلی شی درست کرد یا متد meth را فراخونی کرد؟ :

کد:
namespace MultiClassTest
{
    class MyClass1
    {
        public class MyClass2
        {
            public string x = "1";
            public string meth()
            {
                string y = "internal class";
                return y;
            }
        }
    }
}


در داخل MyClass1 که نیازی به اشاره به خود MyClass1 نیست :
کد:
            MyClass2 a = new MyClass2();
            a.meth();

اما خارج از بدنه MyClass1 باید مشخص کنید که کلاس MyClass2 شما در MyClass1 تعریف شده :
کد:
        MyClass1.MyClass2 x = new MyClass1.MyClass2();
        x.meth();


فضای نام تو در تو رو فهمیدم که باید فضای نام ها را با استفاده از using و نوشتن نام فضای نام و بعد با گذاشتن نقطه و بعد نوشتن فضای نام داخلی ، ملحق کنیم



منظورتون اینه که اگه A کلاس پدربزرگ و B پدر و C فرزند باشه و مثلا متد Test در کلاس پدربزرگ یعنی کلاس A بصورت virtual تعریف شده باشه و بعد در کلاس B یه override از متد Test بسازیم و این متد رو هر جور دلمون خواست تغییر بدیم و بعد حالا میتونیم توی کلاس C متد Test در کلاس A یعنی کلاس پدربزرگ رو دوباره override کنیم؟!
ولی من اینو تست کردم دیدم وقتی میخوایم یه متد رو override کنیم ، فقط آخرین متدی که override کردیم در آخرین کلاس در دسترسمون هست و فقط اونو میتونیم تغییر بدیم و متدهای دیگه در کلاس های قبلی اش که override کردیم از دسترسمون خارج میشه یعنی وقتی در کلاس B که متد رو یه بار override کردیم (چون در کلاس A بصورت virtual تعریف کردیم) ، در دفعه ی بعد که میخوایم override تعریف کنیم یعنی وقتی در کلاس C بصورت override میخوایم بنویسیم ، فقط متد Test ای که در کلاس B (بصورت override) تعریف کردیم در دسترسمون هست و متد Test در کلاس A از دسترس مون خارج میشه
نه چنین منظوری ندارم، همانطور که خودتان دیدید وقتی شما در کلاس میانی برای فرزند متد رو به نوع دیگری override می کنید نه فقط برای اون کلاس، برای فرزندان کلاس هم چنین روالی رو قرار می دهید. اگر قرار بود که فرزندان کلاس همچنان با متد پدربزرگ درگیر بودند که
اصلا override کردن کلاس میانی نادیده گرفته شده بود.


من این تیکه ها رو متوجه نشدم
وقتی در کلاس پدربزرگ که متدم رو public و virtual تعریف کردم و بعد در کلاس پدر بصورت private new تعریف کردم ، از متد فرزند هم به متد مورد نظر در کلاس پدربزرگ دسترسی داشتم یعنی فرزندان ارتباط شون رو با متد در کلاس پدربزرگ از دست ندادن
شما در کلاس پدر نوشته اید private new ، اون private یعنی فقط برای این کلاس متد جدیدی می نویسم و به فرزندانم ربطی ندارند. فرزندان اصلا متد private را نمی بینند که در ارتباط شان تاثیری داشته باشد.
اگر می نوشتید public new ، همانطور که در مثال حقیر وجود داشت، آنوقت قضیه کاملا فرق می کرد.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بازم لطف کردین آقا علی :rose:
من تا اینا رو بخونم ، شما یه سئوال رو که بار آخر ویرایش کردم رو ندیدین که جواب بدین. ببخشید این قدر کلافه تون میکنم . اون سئوال این بود :

یه سئوال دیگه اینکه وقتی توی کلاس پدر ، متدی با قابلیت virtual تعریف میکنم توی هیچ متدی از کلاس پسر با کلمه کلیدی this در دسترس نیست و فقط باید شی براش درست کنم تا در دسترس قرار بگیره . سطح دسترسی شم public هه
مگه کلمه کلیدی this هم کلاس خودی و هم کلاس های اجدادش رو اون عضوهایی که قابلیت دسترسی دارن (بجز public static) رو در دسترس مون قرار نمیده؟
بعد اینکه یه لینک درباره چند ریختی که روون باشه بهم میدین؟ چون این جوری انگار خیلی تو زمینه چند ریختی مشکل دارم و با سئوال پرسیدن هم حل نمیشه . جوری که از مبتدی بگه
ممنون
 
آخرین ویرایش:

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بصورت پیشفرض متغیر سراسری کلاس private ئه مگر اینکه صریحا مشخص کنید، مثلا x اینجا یک متغیر سراسری private ئه :
کد:
    class Class1
    {
        int x;
    }
و با این فرقی نداره :
کد:
    class Class1
    {
        [B][COLOR=#0000FF]private[/COLOR][/B] int x;
    }
و متغیر سراسری private از بیرون کلاس دیده نمی شود، حالا چه برای کلاس فرزند و چه سایر محیط ها.

و مقدار اولیه متغیر های سراسری مقدار پیشفرض نوع داده اونها است، مگر اینکه صریحا مقدار دهی شون کنید، مثلا مقدار پیشفرض int ها صفر ئه، پس مشابه این خواهد بود :
کد:
    class Class1
    {
        private int x [B][COLOR=#0000FF]= 0[/COLOR][/B];
    }

و اینم یه متغیر سراسری private از نوع کلاس Class1 است و مقدار اولیه اش null است، مقدار پیشفرض انواع داده ای که با شیء سر و کار دارند null است :
کد:
    class Class1
    {
        Class3 a;
    }

و این یک متغیر سراسری public از نوع کلاس Class3 است که مقدار اولیه اش یک شیء از همون نوع است :
کد:
    class Class1
    {
        public Class3 a = new Class3();
    }
و متغیر سراسری public از بیرون کلاس قابل مشاهده است، چه فرزند اش باشد و چه نباشد.


هم namespace و هم class ها ساختار سلسله مراتبی رو می پذیرند، همانطور که if و for و سایر بلوک ها می توانند تو در تو باشند.
می توانید داخل یک کلاس کلاس دیگری و داخل فضای نام ای فضای نام دیگری را تعریف کنید.
در هر دو مورد وقتی داخل هم قرار می گیرند ترکیب شون با نقطه انجام میشه، یعنی اگر نام کامل شون رو بخواهید یک کاراکتر . بین شون قرار می گیره، فرضا اگر کلاس B رو داخل کلاس A تعریف کنید، خارج از کلاس A کلاس B رو با نام A.B می شناسند.
همانطور که اگر فضای نام B رو داخل فضای نام A تعریف کنید، مواردی که داخل B می نویسید در فضای نام A.B قرار دارند.

کد:
    public class Class1
    {
        public class Class3
        {

        }
    }

    public class Class2
    {
        public class Class3
        {

        }
    }

    public class Test
    {
        [B][COLOR=#0000FF]Class1.Class3[/COLOR][/B] x;
        [B][COLOR=#0000FF]Class2.Class3[/COLOR][/B] y;
    }
و نکته اینجا است که Class3 با توجه به جایی که به آن اشاره می شود کلاس متفاوتی است، Class1.Class3 و Class2.Class3 دو کلاس کاملا متفاوت اند.




در داخل MyClass1 که نیازی به اشاره به خود MyClass1 نیست :
کد:
            MyClass2 a = new MyClass2();
            a.meth();

اما خارج از بدنه MyClass1 باید مشخص کنید که کلاس MyClass2 شما در MyClass1 تعریف شده :
کد:
        MyClass1.MyClass2 x = new MyClass1.MyClass2();
        x.meth();


نه چنین منظوری ندارم، همانطور که خودتان دیدید وقتی شما در کلاس میانی برای فرزند متد رو به نوع دیگری override می کنید نه فقط برای اون کلاس، برای فرزندان کلاس هم چنین روالی رو قرار می دهید. اگر قرار بود که فرزندان کلاس همچنان با متد پدربزرگ درگیر بودند که
اصلا override کردن کلاس میانی نادیده گرفته شده بود.


شما در کلاس پدر نوشته اید private new ، اون private یعنی فقط برای این کلاس متد جدیدی می نویسم و به فرزندانم ربطی ندارند. فرزندان اصلا متد private را نمی بینند که در ارتباط شان تاثیری داشته باشد.
اگر می نوشتید public new ، همانطور که در مثال حقیر وجود داشت، آنوقت قضیه کاملا فرق می کرد.

واقعا ممنونم ازتون :rose:
نوع داده ای Class3 دیگه چیه برای یه متغییر؟ من تا حالا فقط با نوع داده ای bit (اگه اشتباه نکنم) و short و int و doble و float و string و char و boolean و object آشنا شدم که این آخریه object هم که هر چند دقیق نفهمیدم کاربردش رو ولی انگار خودش یکی از اون انواع داده ای هست
با تعریف new بجر برای ساخت شی و همینطور تعریف آرایه (که هنوز نرسیدم به مبحث آرایه ها) در جای دیگه ای آشنا نیستم
قضیه کلاس های تو در تو رو کاملا متوجه شدم . ممنون . موقع نوشتن نام کلاس باید تو در تو و با نقطه صدا زد
در مورد قسمت آخر هم شما گفته بودین توی پست های قبلی که :
"فرزندان کلاس B ارتباط شان را با Test ئه کلاس A از دست می دهند، چون B از اساس Test جدیدی را virtual کرده"
من الان از این جمله اینو متوجه شدم که وقتی در یک کلاس میانی (کلاس B) متدی بصورت new تعریف کنیم ، باعث میشه وقتی hc کلاس فرزندش یعنی hc کلاس C میخوایم متد نوشته شده در کلاس A (که بصورت virtual بود) رو فراخونی کنیم یا oveeride و ... کنیم ، دیگه این متد در کلاس A از کلاس C در دسترس نخواهد بود
این معنی رو نمیده ؟ پس منظورتون چی بود؟ من دقیق متوجه نشدم
من الان کلا کلمه کلیدی new با new virtual رو نمیدونم دقیق چی کار میکنن ؛ در چه صورتی از چه کلاس هایی در دسترس ان و از این جور سئوالات و یه کم گیج شدم
 

the_king

مدیرکل انجمن
بازم لطف کردین آقا علی :rose:
من تا اینا رو بخونم ، شما یه سئوال رو که بار آخر ویرایش کردم رو ندیدین که جواب بدین. ببخشید این قدر کلافه تون میکنم . اون سئوال این بود :

یه سئوال دیگه اینکه وقتی توی کلاس پدر ، متدی با قابلیت virtual تعریف میکنم توی هیچ متدی از کلاس پسر با کلمه کلیدی this در دسترس نیست و فقط باید شی براش درست کنم تا در دسترس قرار بگیره . سطح دسترسی شم public هه
مگه کلمه کلیدی this هم کلاس خودی و هم کلاس های اجدادش رو اون عضوهایی که قابلیت دسترسی دارن (بجز public static) رو در دسترس مون قرار نمیده؟
بعد اینکه یه لینک درباره چند ریختی که روون باشه بهم میدین؟ چون این جوری انگار خیلی تو زمینه چند ریختی مشکل دارم و با سئوال پرسیدن هم حل نمیشه . جوری که از مبتدی بگه
ممنون

this شیء فعلی ئه، به اصطلاح instance ئه، base شیء جد ئه یعنی شیء ای که پدر شیء فعلی است، این دو با اشیاء متفاوتی سر و کار دارند اما به هر حال متد پدر جزئی از شیء this هم هست،
اگر در لیست اش مشاهده نمی شود مربوط به عدم رعایت موضوعی در کد تان است، مثلا در متد های static دسترسی به this و متد های غیر static وجود ندارد و یا متد های static جزئی از this نیستند چون متعلق به کلاس اند، نه شیء.

از اونجایی که چند ریختی کاربرد اش محدود ئه و اساسا پیچیدگی زیادی داره در آموزش های مرسوم خیلی وارد اش نمی شوند. هر آموزشی در مورد می بینید در حد یکی دو صفحه و با مثال های مقدماتی ئه.
جزو مباحث ابتدایی نیست که دنبال آموزش های سطج مبتدی بگردید، اساسا بیشترین کاربرد چند ریختی برای برنامه نویسان تجاری است که برای استفاده سایرین کتابخانه و کمپوننت می سازند.
وقتی برای خودتان برنامه می نویسید کاربرد چندانی ندارد.

حقیقتا نیازی هم به پرداختن متمرکز به مباحث چند ریختی نیست. در همان حین که به زبان و Framework ئه Net. مسلط می شوید تدریجا چند ریختی رو هم بهتر می شناسید.
توصیه می کنم تا زمانی که در اصول مقدماتی زبان #C هنوز سوالاتی برایتان پیش می آید چند ریختی های تو در تو را نادیده بگیرید، در عین پیچیدگی کاربرد کمی دارند.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
this شیء فعلی ئه، به اصطلاح instance ئه، base شیء جد ئه یعنی شیء ای که پدر شیء فعلی است، این دو با اشیاء متفاوتی سر و کار دارند اما به هر حال متد پدر جزئی از شیء this هم هست،
اگر در لیست اش مشاهده نمی شود مربوط به عدم رعایت موضوعی در کد تان است، مثلا در متد های static دسترسی به this و متد های غیر static وجود ندارد و یا متد های static جزئی از this نیستند چون متعلق به کلاس اند، نه شیء.

از اونجایی که چند ریختی کاربرد اش محدود ئه و اساسا پیچیدگی زیادی داره در آموزش های مرسوم خیلی وارد اش نمی شوند. هر آموزشی در مورد می بینید در حد یکی دو صفحه و با مثال های مقدماتی ئه.
جزو مباحث ابتدایی نیست که دنبال آموزش های سطج مبتدی بگردید، اساسا بیشترین کاربرد چند ریختی برای برنامه نویسان تجاری است که برای استفاده سایرین کتابخانه و کمپوننت می سازند.
وقتی برای خودتان برنامه می نویسید کاربرد چندانی ندارد.

حقیقتا نیازی هم به پرداختن متمرکز به مباحث چند ریختی نیست. در همان حین که به زبان و Framework ئه Net. مسلط می شوید تدریجا چند ریختی رو هم بهتر می شناسید.
توصیه می کنم تا زمانی که در اصول مقدماتی زبان #C هنوز سوالاتی برایتان پیش می آید چند ریختی های تو در تو را نادیده بگیرید، در عین پیچیدگی کاربرد کمی دارند.

خیلی لطف کردین :rose:
یعنی به نظرتون فعلا لازم نیست این کلمه new و new virtual در چند ریختی رو یاد بگیرم؟
 

the_king

مدیرکل انجمن
واقعا ممنونم ازتون :rose:
نوع داده ای Class3 دیگه چیه برای یه متغییر؟ من تا حالا فقط با نوع داده ای bit (اگه اشتباه نکنم) و short و int و doble و float و string و char و boolean و object آشنا شدم که این آخریه object هم که هر چند دقیق نفهمیدم کاربردش رو ولی انگار خودش یکی از اون انواع داده ای هست
با تعریف new بجر برای ساخت شی و همینطور تعریف آرایه (که هنوز نرسیدم به مبحث آرایه ها) در جای دیگه ای آشنا نیستم

لطفا متن های طولانی رو نقل قول نکنید.
شما وقتی class یا struct تعریف می کنید دارید یک نوع داده جدیدی رو ایجاد می کنید. زبان شما رو محدود به یکسری انواع داده ای ابتدایی نمی کنه. object یک نوع داده کلی ئه، مقدار از هر نوع داده می تونه داخل object قرار بگیره.
وقتی متغیری از نوع داده Class3 تعریف می کنید یعنی متغیری که می تواند داخلش یک شیء از نوع Class3 و یا یک شیء از نوع فرزندان Class3 و یا null قرار بگیرد.
new در زبان در جاهای متفاوتی معنای متفاوتی دارد، وقتی می خواهید یک شیء جدید از یک نوع داده بسازید با new به متد سازنده اش دسترسی پیدا می کنید و فراخوانی اش می کنید.

قضیه کلاس های تو در تو رو کاملا متوجه شدم . ممنون . موقع نوشتن نام کلاس باید تو در تو و با نقطه صدا زد
در مورد قسمت آخر هم شما گفته بودین توی پست های قبلی که :
"فرزندان کلاس B ارتباط شان را با Test ئه کلاس A از دست می دهند، چون B از اساس Test جدیدی را virtual کرده"
من الان از این جمله اینو متوجه شدم که وقتی در یک کلاس میانی (کلاس B) متدی بصورت new تعریف کنیم ، باعث میشه وقتی hc کلاس فرزندش یعنی hc کلاس C میخوایم متد نوشته شده در کلاس A (که بصورت virtual بود) رو فراخونی کنیم یا oveeride و ... کنیم ، دیگه این متد در کلاس A از کلاس C در دسترس نخواهد بود
این معنی رو نمیده ؟ پس منظورتون چی بود؟ من دقیق متوجه نشدم
من الان کلا کلمه کلیدی new با new virtual رو نمیدونم دقیق چی کار میکنن ؛ در چه صورتی از چه کلاس هایی در دسترس ان و از این جور سئوالات و یه کم گیج شدم
همینطور ئه، هر کلاسی برای فراخوانی متدی که قابل override شدن ئه دو عنصر base و اسم متد رو در اختیار داره. base کلاس والد ئه و پدر رو بر پدر بزرگ ارجح می دونه. به همین جهت اگر کلاس پدر متد دیگری رو تحت همون نام virtual کنه، ترکیب اون دو عنصر base و نام متد به همون متد جدیدی
هدایت می شود که پدر ارائه کرده، متد ای که پدربزرگ ارائه می کرد هنوز وجود دارد، نابود نشده، ولی از آنجایی که کلاس پدر نامش را به سمت متد دیگری هدایت کرده دیگر قابل دسترسی نیست.

new و new virtual ربطی به دسترسی ندارند، private و public و موارد مشابه اند که دسترسی رو مشخص می کنند.
new در مورد متد ها و مشخصه ها به این معنا است که کلاس والد متد / مشخصه ای تحت همون نام و مشخصات داشته که می خواهیم نادیده اش بگیریم و با تعریف جدیدی ارائه کنیم.
اگر virtual بهش اضافه بشود برای فرزندان این تعریف جدید قابل override کردن است و اگر اضافه نشود فرزندانش حق override کردن متد پدر شان را ندارند. دقت کنید که صریحا اشاره می کنم متد پدر با متد پدربزرگ فرق دارد،
اگر متد پدر از دید فرزندان مخفی باشد (private باشد) می توانند متد پدربزرگ شان را override کنند چون متد private پدر فقط برای پدر تعریف شده.
 

the_king

مدیرکل انجمن
خیلی لطف کردین :rose:
یعنی به نظرتون فعلا لازم نیست این کلمه new و new virtual در چند ریختی رو یاد بگیرم؟

این کلمات کلیدی نیستند که پیچیدگی ایجاد می کنند، کاربرد تو در توی آنها است که پیچیدگی ایجاد می کند.
تمامی عبارات کلیدی زبان رو یاد بگیرید، new و new virtual هم عملکرد شان ساده و مشخص است، اما خودتان را در گیر چند ریختی های تو در تو نکنید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
لطفا متن های طولانی رو نقل قول نکنید.
شما وقتی class یا struct تعریف می کنید دارید یک نوع داده جدیدی رو ایجاد می کنید. زبان شما رو محدود به یکسری انواع داده ای ابتدایی نمی کنه. object یک نوع داده کلی ئه، مقدار از هر نوع داده می تونه داخل object قرار بگیره.
وقتی متغیری از نوع داده Class3 تعریف می کنید یعنی متغیری که می تواند داخلش یک شیء از نوع Class3 و یا یک شیء از نوع فرزندان Class3 و یا null قرار بگیرد.
new در زبان در جاهای متفاوتی معنای متفاوتی دارد، وقتی می خواهید یک شیء جدید از یک نوع داده بسازید با new به متد سازنده اش دسترسی پیدا می کنید و فراخوانی اش می کنید.

سلام
بازم ممنون
میشه این جور گفت که در واقع همون شی هست؟ شی ای که خودمون ایجاد میکنیم؟ یعنی این طور گفت که میشه موقع ساخت شی بهش سطح دسترسی اضافه کرد (البته در سطح کلاس وگرنه داخل متد که شی یا متغییرمون محلی میشه و سطح دسترسی نمیپذیره) ؟
راستی در سطح کلاس میشه چیزی جز متغییرها تعریف کرد!! تا حالا فکر میکردم فقط متغییر میشن
این درسته؟ :
در سطح کلاس فقط نمیشه متد رو فراخونی کرد وگرنه تعریف شی و استراکچر و کلاس و ... میشه. کلا تعاریف ها میشه ولی فراخونی ها نمیشه
------------
راستی منظورتون از چند ریختی تو در تو همون interface ها هستن؟
-----------
میگم new تعریف کردن یک متد ، ربطی به تعریف virtual اون متد در اجدادش نداره . بصورت جداگانه هم انگار میشه تعریف کرد
عملکرد new هم مثل override وقتی از یه کلاس دیگه فراخونی میکنیم با کلمه this ، باعث میشه اجدادش توی لیست نیان . درسته؟ البته ایجاد شی فرق میکنه و میشه هر عضو از کلاس مورد نظر که در دسترسه رو فراخونی کرد با ساخت شی
-----------
آقا کلمه this رو که نام ببریم ، اعضای کلاس فرزند هم در دسترس قرار میده؟

 
آخرین ویرایش:

جدیدترین ارسال ها

بالا