একটি অ-ভার্চুয়াল পদ্ধতি ওভাররাইড করা সম্ভব?


92

একটি অ-ভার্চুয়াল পদ্ধতি ওভাররাইড করার কোনও উপায় আছে? বা এমন কিছু যা অনুরূপ ফলাফল দেয় (পছন্দসই পদ্ধতিতে কল করার জন্য একটি নতুন পদ্ধতি তৈরি করা ব্যতীত)?

Microsoft.Xna.Framework.Graphics.GraphicsDeviceইউনিট পরীক্ষার বিষয়টি মাথায় রেখে কোনও পদ্ধতি আমি ওভাররাইড করতে চাই ।


8
আপনি কি বোঝা বা ওভাররাইড বোঝাতে চান ? ওভারলোড = একই নামের সাথে পৃথক প্যারামিটারগুলির সাথে একটি পদ্ধতি যুক্ত করুন (যেমন কনসোলের বিভিন্ন ওভারলোড। রাইটলাইন)। ওভাররাইড = (মোটামুটিভাবে) পদ্ধতির ডিফল্ট আচরণ পরিবর্তন করুন (উদাহরণস্বরূপ একটি শেপ.ড্রো পদ্ধতি যা বৃত্ত, আয়তক্ষেত্র ইত্যাদির জন্য আলাদা আচরণ করে)। আপনি উদ্ভূত শ্রেণিতে সর্বদা কোনও পদ্ধতি ওভারলোড করতে পারেন তবে ওভাররাইডিং কেবল ভার্চুয়াল পদ্ধতিতে প্রযোজ্য।
itowlson

উত্তর:


112

না, আপনি একটি অ-ভার্চুয়াল পদ্ধতি ওভাররাইড করতে পারবেন না। আপনি যে নিকটতম জিনিসটি করতে পারেন তা হ'ল newএকই নামের সাথে একটি পদ্ধতি তৈরি করে পদ্ধতিটি আড়াল করা তবে এটি ভাল ডিজাইনের নীতিগুলি ভঙ্গ করে বলে এটি উপযুক্ত নয়।

এমনকি কোনও পদ্ধতি লুকিয়ে রাখার পরেও আপনাকে সত্যিকারের ভার্চুয়াল পদ্ধতিতে কল করার মতো পদ্ধতি কলগুলি বহন করার সময় দেয় না pol এই উদাহরণ বিবেচনা করুন:

using System;

class Example
{
    static void Main()
    {
        Foo f = new Foo();
        f.M();

        Foo b = new Bar();
        b.M();
    }
}

class Foo
{
    public void M()
    {
        Console.WriteLine("Foo.M");
    }
}

class Bar : Foo
{
    public new void M()
    {
        Console.WriteLine("Bar.M");
    }
}

এই উদাহরণে উভয় Mপদ্ধতি মুদ্রণ কল Foo.M। যেমন যে বস্তুর রেফারেন্স সঠিক উদ্ভূত ধরনের কিন্তু একটি বেস পদ্ধতি গোপন আপনি যতদিন একটি পদ্ধতি জন্য একটি নতুন বাস্তবায়ন বিস্তার করার অনুমতি দিয়েছেন আপনি এই পদ্ধতির দেখতে পারেন না বিরতি পলিমরফিজম।

আমি আপনাকে সুপারিশ করব যে আপনি এই পদ্ধতিতে বেস পদ্ধতিগুলি গোপন করবেন না।

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

সম্পাদনা করুন: "এক্সিকিউশন সময় পলিমারফিক প্রেরণ" :

আমি এর দ্বারা যা বোঝাচ্ছি তা হ'ল ডিফল্ট আচরণ যা আপনি ভার্চুয়াল পদ্ধতিতে কল করার সময় কার্যকর হয়। উদাহরণস্বরূপ বলা যাক যে আমার আগের কোড উদাহরণে, একটি ভার্চুয়াল-নন পদ্ধতিটি সংজ্ঞায়িত করার পরিবর্তে আমি একটি ভার্চুয়াল পদ্ধতি এবং একটি সত্য ওভাররাইড পদ্ধতিও সংজ্ঞায়িত করেছি।

যদি আমি b.Fooসেই ক্ষেত্রে কল করতে পারি , তবে সিএলআর সঠিকভাবে bরেফারেন্সটি নির্দেশ করে Barএবং যে কলটি Mযথাযথভাবে প্রেরণ করবে তা সঠিকভাবে নির্ধারণ করবে ।


6
যদিও "এক্সিকিউশন টাইম পলিমর্ফিক প্রেরণ" প্রযুক্তিগতভাবে এটি বলার সঠিক উপায়, আমি ধারণা করি এটি সম্ভবত প্রায় সবার মাথায় চলে গেছে!
অরিয়ন এডওয়ার্ডস 0

4
যদিও এটি সত্য যে লেখক হয়তো পদ্ধতিটিকে ওভাররাইড করার বিষয়টি অস্বীকার করার ইচ্ছা পোষণ করেছিলেন এটি সত্য নয় যে এটি করা সঠিকভাবে ছিল। আমি মনে করি যে ব্যবহারকারীকে ডিবাগিং এবং ইউনিট পরীক্ষায় আরও নমনীয়তার সুযোগ দেওয়ার জন্য এক্সএনএ দলের একটি আইগ্রাফিক্স ডিভাইস ইন্টারফেস প্রয়োগ করা উচিত ছিল। আমি কিছু খুব কুৎসিত কাজ করতে বাধ্য হই এবং এটি দলটি আগে থেকেই দেখে নেওয়া উচিত ছিল। আরও আলোচনা এখানে পাওয়া যাবে: forums.xna.com/forums/p/30645/226222.aspx
zfedoran

4
@ ওরিওন আমি এটি বুঝতে পারি নি তবে দ্রুত গুগলের পরে আমি "সঠিক" শর্তাদি ব্যবহার করে প্রশংসা করেছি।
zfedoran

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

4
সুতরাং আপনি যখন একটি বৃহত কোডবেস উত্তরাধিকারী হন তখন কী হবে এবং নতুন কার্যকারিতার জন্য একটি পরীক্ষা যুক্ত করা দরকার তবে এটি পরীক্ষা করার জন্য আপনাকে পুরো প্রচুর যন্ত্রপাতি ইনস্ট্যান্ট করতে হবে। জাভাতে, আমি কেবল সেই অংশগুলি প্রসারিত করব এবং স্টাবগুলি সহ প্রয়োজনীয় পদ্ধতিগুলি ওভাররাইড করব। সি # তে, যদি পদ্ধতিগুলিকে ভার্চুয়াল হিসাবে চিহ্নিত না করা হয় তবে আমাকে অন্য কিছু প্রক্রিয়া খুঁজে বের করতে হবে (উপহাসের পাঠাগার বা এই জাতীয়, এবং তারপরেও)।
অ্যাডাম পার্কিন

22

না আপনি পারবেন না।

আপনি কেবল ভার্চুয়াল পদ্ধতিতে ওভাররাইড করতে পারেন - এখানে এমএসডিএন দেখুন :

সি # তে, উত্পন্ন ক্লাসগুলিতে বেস শ্রেণীর পদ্ধতিগুলির মতো একই নামের পদ্ধতি থাকতে পারে।

  • বেস ক্লাস পদ্ধতিটি ভার্চুয়ালকে সংজ্ঞায়িত করতে হবে।

6

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


3

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

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

কোনও বিদ্যমান ক্লাসে আপনাকে ওভারলোড যুক্ত হতে বাধা দেওয়ার কোনও কিছুই নেই, তবে কেবল আপনার কোড সম্পর্কে জানে এমন কোডই এটি অ্যাক্সেস করতে সক্ষম হবে।


2

আপনি সি # তে কোনও শ্রেণির নন-ভার্চুয়াল পদ্ধতিকে ওভাররাইড করতে পারবেন না (সিএলআর হ্যাকিং ছাড়াই), তবে আপনি শ্রেণি প্রয়োগকারীদের ইন্টারফেসের যে কোনও পদ্ধতি ওভাররাইড করতে পারেন। বিবেচনা করুন আমাদের সিল নেই

class GraphicsDevice: IGraphicsDevice {
    public void DoWork() {
        Console.WriteLine("GraphicsDevice.DoWork()");
    }
}

// with its interface
interface IGraphicsDevice {
    void DoWork();
}

// You can't just override DoWork in a child class,
// but if you replace usage of GraphicsDevice to IGraphicsDevice,
// then you can override this method (and, actually, the whole interface).

class MyDevice: GraphicsDevice, IGraphicsDevice {
    public new void DoWork() {
        Console.WriteLine("MyDevice.DoWork()");
        base.DoWork();
    }
}

এবং এখানে ডেমো

class Program {
    static void Main(string[] args) {

        IGraphicsDevice real = new GraphicsDevice();
        var myObj = new MyDevice();

        // demo that interface override works
        GraphicsDevice myCastedToBase = myObj;
        IGraphicsDevice my = myCastedToBase;

        // obvious
        Console.WriteLine("Using real GraphicsDevice:");
        real.DoWork();

        // override
        Console.WriteLine("Using overriden GraphicsDevice:");
        my.DoWork();

    }
}


0

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


0

একটি অ-ভার্চুয়াল পদ্ধতি ওভাররাইড করার কোনও উপায় আছে? বা এমন কিছু যা অনুরূপ ফলাফল দেয় (পছন্দসই পদ্ধতিতে কল করার জন্য একটি নতুন পদ্ধতি তৈরি করা ব্যতীত)?

আপনি একটি অ-ভার্চুয়াল পদ্ধতি ওভাররাইড করতে পারবেন না। তবে আপনি অনুরূপ ফলাফল পেতে সংশোধক কীওয়ার্ডটি ব্যবহার করতে পারেন new:

class Class0
{
    public int Test()
    {
        return 0;
    }
}

class Class1 : Class0
{
    public new int Test()
    {
        return 1;
    }
}
. . .
// result of 1
Console.WriteLine(new Class1().Test());

আপনিও নিশ্চিত করতে চাইবেন যে অ্যাক্সেস মডিফায়ারটিও একই রকম, অন্যথায় আপনি উত্তরাধিকার সূত্রে পাবেন না। থেকে অন্য ক্লাসে উত্তরাধিকারী তাহলে মধ্যে শব্দ প্রভাবিত করবে না বস্তু তা থেকে উত্তরাধিকার সূত্রে প্রাপ্ত, যদি না এক্সেস পরিবর্তক একই।Class1newClass1

অ্যাক্সেস মডিফায়ারটি যদি একই না হয়:

class Class0
{
    protected int Test()
    {
        return 0;
    }
}

class Class1 : Class0
{
    // different access modifier
    new int Test()
    {
        return 1;
    }
}

class Class2 : Class1
{
    public int Result()
    {
        return Test();
    }
}
. . .
// result of 0
Console.WriteLine(new Class2().Result());

... বনাম যদি এক্সেস পরিবর্তক হয় একই:

class Class0
{
    protected int Test()
    {
        return 0;
    }
}

class Class1 : Class0
{
    // same access modifier
    protected new int Test()
    {
        return 1;
    }
}

class Class2 : Class1
{
    public int Result()
    {
        return Test();
    }
}
. . .
// result of 1
Console.WriteLine(new Class2().Result());

পূর্বের উত্তরে যেমন উল্লেখ করা হয়েছে, এটি কোনও ভাল নকশার নীতি নয়।


-5

বিমূর্ত শ্রেণি এবং বিমূর্ত পদ্ধতি ব্যবহার করে এটি অর্জনের একটি উপায় রয়েছে।

বিবেচনা

Class Base
{
     void MethodToBeTested()
     {
        ...
     }

     void Method1()
     {
     }

     void Method2()
     {
     }

     ...
}

এখন, আপনি যদি পদ্ধতি মেথডোবেস্টেড () এর বিভিন্ন সংস্করণ রাখতে চান, তবে ক্লাস বেসটি একটি বিমূর্ত শ্রেণিতে এবং পদ্ধতি মেথডোবিস্টেস্ট () বিমূর্ত পদ্ধতি হিসাবে পরিবর্তন করুন

abstract Class Base
{

     abstract void MethodToBeTested();

     void Method1()
     {
     }

     void Method2()
     {
     }

     ...
}

বিমূর্ত শূন্যতার সাথে মেথডোবেস্টেড () আসে একটি সমস্যা; বাস্তবায়ন চলে গেছে।

সুতরাং class DefaultBaseImplementation : Baseডিফল্ট বাস্তবায়ন করতে একটি তৈরি করুন ।

এবং class UnitTestImplementation : Baseইউনিট পরীক্ষার বাস্তবায়ন করতে অন্যটি তৈরি করুন ।

এই 2 টি নতুন ক্লাসের সাথে, বেস শ্রেণীর কার্যকারিতা ওভাররাইড করা যায়।

Class DefaultBaseImplementation : Base    
{
    override void MethodToBeTested()    
    {    
        //Base (default) implementation goes here    
    }

}

Class UnitTestImplementation : Base
{

    override void MethodToBeTested()    
    {    
        //Unit test implementation goes here    
    }

}

এখন আপনার 2 টি ক্লাস বাস্তবায়ন হচ্ছে (ওভাররাইডিং) MethodToBeTested()

আপনি প্রয়োজনীয় হিসাবে (উদ্ভূত) শ্রেণি ইনস্ট্যান্ট করতে পারেন (উদাহরণস্বরূপ বেস বাস্তবায়ন বা ইউনিট পরীক্ষার বাস্তবায়ন সহ)।


@ স্লাভু: হাই স্লাভু কোড আপডেটের জন্য ধন্যবাদ। তবে আপনি কি দয়া করে আমাকে এটিকে হ্রাস করার কারণ বলতে পারবেন?
শিবানন্দ

6
কারণ এটি প্রশ্নের উত্তর দেয় না। তিনি জিজ্ঞাসা করছেন যে আপনি ভার্চুয়াল চিহ্নিত না করে সদস্যদের ওভাররাইড করতে পারেন কিনা। আপনি দেখিয়েছেন যে আপনাকে বিমূর্তভাবে চিহ্নিত সদস্য প্রয়োগ করতে হবে।
লি লুভিয়ের
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.