সি # - কীওয়ার্ড ব্যবহার ভার্চুয়াল + ওভাররাইড বনাম নতুন


204

বেস টাইপের পদ্ধতি " virtual" ঘোষণার মধ্যে এবং "চাইল্ড টাইপের সাথে ম্যাচিং পদ্ধতিটি ঘোষণার সময় override" new"কীওয়ার্ডটি ব্যবহার করার বিপরীতে " "কীওয়ার্ড ব্যবহার করে কোনও শিশু টাইপের মধ্যে ওভাররাইড করার মধ্যে কী পার্থক্য রয়েছে ?


3
এমএসডিএন বলছে "ব্যবহার newএকই নামের সাথে একটি নতুন সদস্য তৈরি করে এবং আসল সদস্যকে গোপনে পরিণত করে, overrideউত্তরাধিকার সূত্রে প্রাপ্ত সদস্যের জন্য প্রয়োগকে প্রসারিত করে"
আমিন এম


উত্তর:


181

"নতুন" কীওয়ার্ডটি ওভাররাইড করে না, এটি একটি নতুন পদ্ধতিকে বোঝায় যা বেস ক্লাস পদ্ধতির সাথে কোনও সম্পর্ক রাখে না।

public class Foo
{
     public bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public new bool DoSomething() { return true; }
}

public class Test
{
    public static void Main ()
    {
        Foo test = new Bar ();
        Console.WriteLine (test.DoSomething ());
    }
}

এটি মিথ্যা প্রিন্ট করে, আপনি যদি ওভাররাইড ব্যবহার করেন তবে এটি সত্যই মুদ্রিত হত।

(জোসেফ ডাইগলের কাছ থেকে নেওয়া বেস কোড)

সুতরাং, যদি আপনি প্রকৃত পলিমারফিজম করছেন তবে আপনার অবশ্যই সর্বদা .র্ধ্বমুখী হওয়া উচিত । আপনার কেবলমাত্র "নতুন" ব্যবহার করার দরকারের জায়গাটি যখন পদ্ধতিটি কোনওভাবে কোনও শ্রেণীর সংস্করণের সাথে সম্পর্কিত না হয়।


আপনার কোডটি সংশোধন করা উচিত, আমি পদ্ধতিগুলি স্থির করেছিলাম (যা "নতুন" কীওয়ার্ড ব্যবহারের জন্য বৈধ)। তবে আমি সিদ্ধান্ত নিয়েছি যে উদাহরণগুলির পদ্ধতিগুলি ব্যবহার করা আরও পরিষ্কার।
জোসেফ ডাইগল

1
ধন্যবাদ, আমি "স্ট্যাটিক" অংশটি মিস করেছি। ভবিষ্যতের দিকে আরও মনোযোগ দেওয়া উচিত
অ্যালবার্টেইন

1
নোট করুন যে এখানে লু Foo পরীক্ষা = নতুন বার () অত্যন্ত গুরুত্বপূর্ণ, মেটোডগুলির জন্য নতুন / ওভাররাইড কীওয়ার্ডটি নির্ধারণ করে যে আপনি যখন কোনও Foo ভেরিয়েবলের মধ্যে একটি বার রাখেন তখন কোন metod বলা হয়।
থমাস এন

... তাই এটি কেবল যেমন সঠিক একই না থাকার virtualবেস এবং overrideউদ্ভূত হয়? কেন এটি বিদ্যমান? কোডটি এখনও ডাব্লু / ও পর্যন্ত চলবে new- সুতরাং এটি কি খাঁটিভাবে কেবল পঠনযোগ্যতা?
ডন চ্যাডল

আপনার উত্তর প্রিয় স্যার বেশ অস্পষ্ট। নতুন এবং ভার্চুয়াল-ওভাররাইডগুলি একই জিনিসটি করে, কেবলমাত্র পার্থক্য হ'ল নতুন পিতামাতার ক্লাসে পদ্ধতিটি আড়াল করে এবং ওভাররাইড .. ভাল, এটি ওভাররাইড করে। অবশ্যই এটি মিথ্যা প্রিন্ট করে কারণ আপনার পরীক্ষার অবজেক্টটি টাইপ ফু, এটি যদি বার টাইপের হয় তবে এটি সত্য মুদ্রণ করে। যদিও খুব জটিল উদাহরণ।
মিঃসাইলেন্ট

228

আমি সবসময় ছবিগুলির মাধ্যমে আরও সহজে বোঝা যায় এমন জিনিসগুলি দেখতে পাই:

আবার জোসেফ ডাইগলের কোড নিচ্ছেন,

public class Foo
{
     public /*virtual*/ bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public /*override or new*/ bool DoSomething() { return true; }
}

আপনি যদি তখন কোডটি কল করেন:

Foo a = new Bar();
a.DoSomething();

দ্রষ্টব্য: গুরুত্বপূর্ণ বিষয়টি হ'ল আমাদের অবজেক্টটি আসলে একটি Barতবে আমরা এটি একটি ধরণের ভেরিয়েবলে সংরক্ষণ করিFoo ( এটি এটি ingালাইয়ের অনুরূপ)

তারপরে ফলাফলটি আপনি virtual/ overrideবা newআপনার ক্লাসগুলি ঘোষণার সময় ব্যবহার করেছেন কিনা তার উপর নির্ভর করে নীচে থাকবে ।

ভার্চুয়াল / ওভাররাইড ব্যাখ্যা চিত্র


3
ধন্যবাদ .... তবে আপনি যে কাস্টিং বলেছেন তার বিষয়ে উপরের ছবি সম্পর্কে কিছুটা ব্যাখ্যা করতে পারেন?
ওডিসিহ

উফ যদি আমার পূর্ববর্তীগুলিতে এই কয়েকটি লাইন যুক্ত করতে ভুলে যায়। মন্তব্য: আপনার অর্থ কি ভার্চুয়াল / ওভাররাইডিং এবং অ-ভিটুয়াল / নতুন কেবল পলিমারফিজ্ম ধারণার জন্য ব্যবহৃত হয় এবং যখন আপনি কেবল কোনও ভেরিয়েবল ঘোষণা করেন (কাস্টিং ব্যবহার করছেন না) তার অর্থ কি না? আবার ধন্যবাদ.
ওডিসিহ

এই উত্তরটি আমি ঠিক যা খুঁজছিলাম is আমার একমাত্র সমস্যা হ'ল ফ্লিকার চিত্রগুলি আমার কর্মস্থলে ব্লক করা আছে তাই আমার ফোনের মাধ্যমে এটি অ্যাক্সেস করতে হয়েছিল ...
mezoid

7
প্রশ্নের উত্তর দেওয়ার আসল প্রচেষ্টা।
আইমেটোরিয়া

আমি ছবিটি ঠিক করতে পারব কিনা? তার Corp ফায়ারওয়ালের পিছনে অবরুদ্ধ ...
জেরেমি থম্পসন

43

ভার্চুয়াল এবং অ-ভার্চুয়াল পদ্ধতির আচরণের পার্থক্য বুঝতে এখানে কিছু কোড রয়েছে:

class A
{
    public void foo()
    {
        Console.WriteLine("A::foo()");
    }
    public virtual void bar()
    {
        Console.WriteLine("A::bar()");
    }
}

class B : A
{
    public new void foo()
    {
        Console.WriteLine("B::foo()");
    }
    public override void bar()
    {
        Console.WriteLine("B::bar()");
    }
}

class Program
{
    static int Main(string[] args)
    {
        B b = new B();
        A a = b;
        a.foo(); // Prints A::foo
        b.foo(); // Prints B::foo
        a.bar(); // Prints B::bar
        b.bar(); // Prints B::bar
        return 0;
    }
}

এর জন্য আপনাকে ধন্যবাদ - তবে কেন newবেস পদ্ধতি "লুকানোর" জন্য ব্যবহার করবেন, যখন কেবল ওভাররাইড ব্যবহার না করে একই কাজ করা হয়?
ডন চ্যাডল

1
আমি মনে করি না এটি বেস ক্লাসকে ওভারডেন হতে আটকাতে তৈরি করা হয়েছিল। আমি মনে করি নাম সংঘর্ষ এড়ানোর জন্য এটি তৈরি করা হয়েছিল কারণ আপনি এমন কোনও পদ্ধতি ওভাররাইড করতে পারবেন না যা নয় virtualএবং সংকলক অভিযোগ করবে যদি কোনও শ্রেণি "ব্লাডলাইন" তে একই ফাংশনের নামটি virtualস্বাক্ষরবিহীন
দেখায়

19

newশব্দ আসলে একটি সম্পূর্ণ নতুন সদস্য যে শুধুমাত্র নির্দিষ্ট ধরনের উপর বিদ্যমান সৃষ্টি করে।

এই ক্ষেত্রে

public class Foo
{
     public bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public new bool DoSomething() { return true; }
}

পদ্ধতি উভয় প্রকারে বিদ্যমান। আপনি যখন প্রতিবিম্ব ব্যবহার করেন এবং প্রকারের সদস্যগুলি পান Bar, আপনি আসলে 2 টি পদ্ধতি খুঁজে পাবেন DoSomething()যা একেবারে একই চেহারা বলে । newবেস ক্লাসে কার্যকরভাবে প্রয়োগটি গোপন করে আপনার ব্যবহার করে , যাতে ক্লাসগুলি যখন Bar(আমার উদাহরণস্বরূপ) থেকে প্রাপ্ত হয় তখন মেথড কলটি যেভাবে base.DoSomething()আসে Barএবং না Foo


9

ভার্চুয়াল / ওভাররাইড সংস্থাপককে বলে যে দুটি পদ্ধতি সম্পর্কিত এবং কিছু পরিস্থিতিতে যখন আপনি মনে করবেন যে আপনি প্রথম (ভার্চুয়াল) পদ্ধতিটি কল করছেন এটি পরিবর্তে দ্বিতীয় (ওভাররাইড) পদ্ধতিতে কল করা ঠিক। এটি পলিমারফিজমের ভিত্তি।

(new SubClass() as BaseClass).VirtualFoo()

সাবক্লাসের ওভারডিডেন ভার্চুয়ালফু () পদ্ধতিতে কল করবে।

নতুন সংকলককে বলে যে আপনি বেস শ্রেণিতে একটি পদ্ধতি হিসাবে একই নামের সাথে একটি উত্পন্ন শ্রেণিতে একটি পদ্ধতি যুক্ত করছেন, তবে তাদের একে অপরের সাথে কোনও সম্পর্ক নেই।

(new SubClass() as BaseClass).NewBar()

বেসক্লাসের নতুনবার () পদ্ধতিতে কল করবে, যেখানে:

(new SubClass()).NewBar()

সাবক্লাসের নতুনবার () পদ্ধতিতে কল করবে।


সত্যিই এই বাক্যটি "সংকলকটি বলে"
মিনা গ্যাব্রিয়েল

"পলিমারফিজমের ভিত্তি" আরেকটি উত্কৃষ্ট বক্তব্য :)
জেরেমি থম্পসন

8

কেবল প্রযুক্তিগত বিশদ ছাড়াই আমি মনে করি ভার্চুয়াল / ওভাররাইড ব্যবহার করে ডিজাইনে প্রচুর অর্থবোধক তথ্য যোগাযোগ করা হয়। আপনি যখন কোনও পদ্ধতি ভার্চুয়াল ঘোষণা করেন, আপনি নির্দেশিত হন যে বাস্তবায়নকারী ক্লাসগুলি তাদের নিজস্ব, অ-ডিফল্ট বাস্তবায়ন সরবরাহ করতে চাইতে পারে expect এটি একটি বেস ক্লাসে ছেড়ে দেওয়া, একইভাবে, প্রত্যাশা ঘোষণা করে যে ডিফল্ট পদ্ধতিটি সমস্ত বাস্তবায়নকারী শ্রেণীর জন্য যথেষ্ট হবে। একইভাবে, কেউ বাস্তবায়নকারী ক্লাসগুলিকে তাদের নিজস্ব বাস্তবায়ন সরবরাহ করতে বাধ্য করার জন্য বিমূর্ত ঘোষণাগুলি ব্যবহার করতে পারেন। আবার, আমি মনে করি এটি প্রোগ্রামার কোডটি কীভাবে ব্যবহার করবে বলে আশা করে সে সম্পর্কে অনেক যোগাযোগ করে। আমি যদি বেস এবং প্রয়োগকারী ক্লাস উভয়ই লিখতে থাকি এবং নিজেকে নতুন ব্যবহার করতে দেখি আমি পিতামাতার মধ্যে পদ্ধতিটি ভার্চুয়াল না করার সিদ্ধান্তটি গুরুত্বের সাথে পুনর্বিবেচনা করব এবং আমার উদ্দেশ্যটি বিশেষভাবে ঘোষণা করব


নতুন বনাম ওভাররাইডের প্রযুক্তিগত ব্যাখ্যাগুলি দুর্দান্ত, তবে এই উত্তরটি ডিভসকে ব্যবহার করার জন্য গাইড করার জন্য সর্বাধিক সহায়তা করে বলে মনে হচ্ছে।
সুলি

4

ওভাররাইড কীওয়ার্ড এবং নতুন কীওয়ার্ডের মধ্যে পার্থক্যটি হ'ল প্রাক্তন পদ্ধতিটি ওভাররাইড করে এবং পরে পদ্ধতিটি লুকায় iding

আরও তথ্যের জন্য অনুসরণীয় লিঙ্কগুলি দেখুন ...

এমএসডিএন এবং অন্যান্য


3
  • newকীওয়ার্ড হিডিংয়ের জন্য। - মানে আপনি রানটাইমে আপনার পদ্ধতিটি গোপন করছেন। আউটপুট বেস ক্লাস পদ্ধতি ভিত্তিক করা হবে।
  • overrideওভাররাইডিংয়ের জন্য। - এর অর্থ আপনি বেস শ্রেণীর রেফারেন্স সহ আপনার উদ্ভূত শ্রেণির পদ্ধতিটি চাচ্ছেন। আউটপুট উত্সর্গীকৃত শ্রেণি পদ্ধতির উপর ভিত্তি করে তৈরি হবে।

1

আমার ব্যাখ্যাটির সংস্করণটি পার্থক্যগুলি বুঝতে সহায়তা করার জন্য বৈশিষ্ট্যগুলি ব্যবহার করে আসে ।

overrideযথেষ্ট সহজ, তাই না? অন্তর্নিহিত প্রকারটি পিতামাতারকে ওভাররাইড করে।

newসম্ভবত বিভ্রান্তিকর (আমার জন্য এটি ছিল)। বৈশিষ্ট্য সহ এটি বোঝা সহজ:

public class Foo
{
    public bool GetSomething => false;
}

public class Bar : Foo
{
    public new bool GetSomething => true;
}

public static void Main(string[] args)
{
    Foo foo = new Bar();
    Console.WriteLine(foo.GetSomething);

    Bar bar = new Bar();
    Console.WriteLine(bar.GetSomething);
}

একটি ডিবাগার ব্যবহার করে আপনি যে লক্ষ্য করতে Foo fooহয়েছে 2 GetSomething , বৈশিষ্ট্য যেমন আসলে সম্পত্তির 2 সংস্করণ রয়েছে Foo's এবং Bar' s, এবং জানেন যে যা ব্যবহার করার জন্য এক, গ # "অকার্যকর" বর্তমান টাইপ জন্য সম্পত্তি।

আপনি যদি বারটির সংস্করণটি ব্যবহার করতে চান তবে আপনি ওভাররাইড বা Foo fooপরিবর্তে ব্যবহার করতে পারতেন ।

Bar barএটির জন্য কেবল 1 রয়েছে , কারণ এটি সম্পূর্ণ নতুন আচরণ চায় GetSomething


0

কোনও কিছুর সাথে কোনও পদ্ধতি চিহ্নিত না করার অর্থ: অবজেক্টের কম্পাইল টাইপ ব্যবহার করে এই পদ্ধতিটি বেঁধে রাখুন, রানটাইম টাইপ নয় (স্ট্যাটিক বাইন্ডিং)।

কোনও পদ্ধতিকে virtualঅর্থ সহ চিহ্নিত করা : অবজেক্টের রানটাইম টাইপ ব্যবহার করে এই পদ্ধতিটি বেঁধে রাখুন, টাইপ টাইপ (ডায়নামিক বাইন্ডিং) সংকলন করবেন না।

উত্সযুক্ত শ্রেণীর virtualসাথে একটি বেস শ্রেণীর পদ্ধতি চিহ্নিত করার overrideঅর্থ: অবজেক্টের রানটাইম টাইপ (গতিশীল বাঁধাই) ব্যবহার করে আবদ্ধ হওয়া এই পদ্ধতি।

উত্সযুক্ত শ্রেণীর virtualসাথে একটি বেস শ্রেণীর পদ্ধতি চিহ্নিত করার newঅর্থ: এটি একটি নতুন পদ্ধতি, যার বেস শ্রেণিতে একই নামটির সাথে কোনও সম্পর্ক নেই এবং এটি অবজেক্টের সংকলন টাইম টাইপ (স্ট্যাটিক বাইন্ডিং) ব্যবহার করে আবদ্ধ হওয়া উচিত।

virtualউত্পন্ন শ্রেণিতে একটি বেস শ্রেণীর পদ্ধতি চিহ্নিত না করার অর্থ: এই পদ্ধতিটি new(স্ট্যাটিক বাইন্ডিং) হিসাবে চিহ্নিত করা হয় ।

একটি পদ্ধতি চিহ্নিত করার abstractঅর্থ: এই পদ্ধতিটি ভার্চুয়াল, তবে আমি এটির জন্য কোনও বডি ঘোষণা করব না এবং এর শ্রেণিটিও বিমূর্ত (গতিশীল বাঁধাই)।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.