কখন এবং কেন নেস্টেড ক্লাস ব্যবহার করবেন?


30

অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং ব্যবহার করে আমাদের ক্লাসের (একটি নেস্টেড ক্লাস) ভিতরে একটি ক্লাস তৈরি করার ক্ষমতা আছে তবে আমি আমার 4 বছরের কোডিংয়ের অভিজ্ঞতায় কখনও নেস্টেড ক্লাস তৈরি করি নি।
নেস্টেড ক্লাসগুলি কিসের জন্য ভাল?

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

কোন পরিস্থিতিতে নেস্টেড ক্লাস ব্যবহার করা উচিত বা অন্যান্য কৌশলগুলির তুলনায় সেগুলি আরও শক্তিশালী?


1
আপনার কিছু ভাল উত্তর আছে এবং আমার মাঝে মাঝে কিছু শ্রমজীবী ​​বা স্ট্রুট থাকে যা আমার কেবল শ্রেণীর ভিতরে প্রয়োজন।
পাপারাজ্জো

উত্তর:


19

নেস্টেড ক্লাসগুলির প্রধান বৈশিষ্ট্য হ'ল তারা কোনও শ্রেণীর নিজস্ব সম্পূর্ণ ক্ষমতা থাকা অবস্থায় বাইরের শ্রেণীর ব্যক্তিগত সদস্যদের অ্যাক্সেস করতে পারে। এছাড়াও তারা ব্যক্তিগত হতে পারে যা কিছু পরিস্থিতিতে কিছুটা পাওয়ারফুল এনক্যাপসুলেশনের অনুমতি দেয়:

এখানে আমরা সেটারটিকে সম্পূর্ণ কারখানায় লক করে রাখি কারণ শ্রেণিটি বেসরকারী হওয়ায় কোনও গ্রাহক এটি ডাউনকাস্ট করতে এবং সেটারটি অ্যাক্সেস করতে পারবেন না এবং যা অনুমোদিত তা আমরা সম্পূর্ণরূপে নিয়ন্ত্রণ করতে পারি।

public interface IFoo 
{
    int Foo{get;}      
}
public class Factory
{
    private class MyFoo : IFoo
    {
        public int Foo{get;set;}
    }
    public IFoo CreateFoo(int value) => new MyFoo{Foo = value};
}

এর বাইরে এটি একটি নিয়ন্ত্রিত পরিবেশে তৃতীয় পক্ষের ইন্টারফেস প্রয়োগের জন্য দরকারী যেখানে আমরা এখনও ব্যক্তিগত সদস্যদের অ্যাক্সেস করতে পারি।

আমরা উদাহরণস্বরূপ যদি অন্য কিছু অবজেক্টের জন্য কিছু ইন্টারফেসের উদাহরণ সরবরাহ করি তবে আমরা চাই না যে আমাদের মূল শ্রেণি এটি প্রয়োগ করে আমরা একটি অভ্যন্তরীণ শ্রেণিকে এটি প্রয়োগ করতে পারি।

public class Outer
{
    private int _example;
    private class Inner : ISomeInterface
    {
        Outer _outer;
        public Inner(Outer outer){_outer = outer;}
        public int DoStuff() => _outer._example;
    }
    public void DoStuff(){_someDependency.DoBar(new Inner(this)); }
}

বেশিরভাগ ক্ষেত্রে আমি প্রত্যাশা করি যে আপনি দ্বিতীয় উদাহরণে যা দেখিয়েছেন সেগুলি করার একটি পরিষ্কার উপায় হতে পারে
বেন অ্যারনসন

@ বেনআরনসন আপনি কীভাবে প্রতিনিধিদের ব্যবহার করে এলোমেলো ইন্টারফেস প্রয়োগ করবেন?
এসবেন স্কোভ পেডারসেন

@ এসবেনস্কভ পিডারসন আপনার উদাহরণের জন্য ভাল উদাহরণস্বরূপ পাস করার পরিবর্তে Outerআপনি একটি পাস করেছিলেন Func<int>যা ঠিক হবে() => _example
বেন অ্যারোনসন

@ বেনআরনসন এই অত্যন্ত সাধারণ ক্ষেত্রে আপনি ঠিক বলেছেন তবে আরও জটিল উদাহরণের জন্য অনেক প্রতিনিধি আনাড়ি হয়ে যায়।
এসবেভ স্কভ পেদারসেন

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

23

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

আমি বিশ্বাস করি এটি প্রায়শই এমন একটি পদ্ধতি প্রয়োগ করে ঘটে যা কোনও ইন্টারফেস প্রয়োগ করে কোনও বস্তুকে ফেরত দেয় এবং আমরা সেই বস্তুর কংক্রিটের ধরণটি গোপন রাখতে চাই কারণ এটি অন্য কোথাও কার্যকর হবে না।

আইনিউমারেবল বাস্তবায়ন করা এর একটি ভাল উদাহরণ:

class BlobOfBusinessData: IEnumerable<BusinessDatum>
{
    public IEnumerator<BusinessDatum> GetEnumerator()
    {
         return new BusinessDatumEnumerator(...);
    }

    class BusinessDatumEnumerator: IEnumerator<BusinessDatum>
    {
        ...
    }
}

বাইরের কাউকেই BlobOfBusinessDataকংক্রিটের BusinessDatumEnumeratorধরণ সম্পর্কে জানার বা যত্ন নেওয়ার কোনও কারণ নেই , তাই আমরা পাশাপাশি এটি ভিতরে রাখতে পারি BlobOfBusinessData

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


6
আমি নতুন প্রোগ্রামারদের সাথে যে অন্য উদাহরণটি ব্যবহার করি তা হ'ল একটি Nodeক্লাস LinkedList। যে কেউ ব্যবহার করে LinkedListসে কীভাবে Nodeপ্রয়োগ করা হয় তা ততক্ষণ চিন্তা করে না যতক্ষণ না তারা সামগ্রীগুলি অ্যাক্সেস করতে পারে। একমাত্র সত্তা যা একেবারেই যত্ন করে তা হ'ল LinkedListশ্রেণি।
ম্যাজ জে

3

তাহলে কেন নেস্টেড ক্লাস তৈরি করবেন?

আমি কয়েকটি গুরুত্বপূর্ণ কারণ সম্পর্কে ভাবতে পারি:

1. এনক্যাপসুলেশন সক্ষম করুন

অনেক সময় নেস্টেড ক্লাসগুলি ক্লাসের প্রয়োগের বিবরণ দেয়। প্রধান শ্রেণীর ব্যবহারকারীদের তাদের অস্তিত্ব সম্পর্কে যত্ন নেওয়া উচিত নয়। প্রধান শ্রেণীর ব্যবহারকারীদের কোড পরিবর্তন করার প্রয়োজন ছাড়াই আপনার ইচ্ছামত এগুলি পরিবর্তন করতে সক্ষম হওয়া উচিত।

২. নাম দূষণ এড়ান

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

আসুন কেন একটি নেস্টেড বর্গকে মূল শ্রেণীর মতো একই স্কোপে স্থানান্তরিত করাই তা বোঝানোর জন্য একটি সরল উদাহরণ বানাতে পারি নাম হ'ল নাম দূষণ। ধরা যাক আপনি একটি লিঙ্কযুক্ত তালিকার শ্রেণি প্রয়োগ করছেন। সাধারণত, আপনি ব্যবহার করতে হবে

publid class LinkedList
{
   class Node { ... }
   // Use Node to implement the LinkedList class.
}

আপনি যদি Nodeসেই একই সুযোগে চলে যাওয়ার সিদ্ধান্ত নেন তবে আপনার কাছে তা LinkedListথাকবে

public class LinkedListNode
{
}

public class LinkedList
{
  // Use LinkedListNode to implement the class
}

LinkedListNodeLinkedListক্লাস নিজেই ছাড়া দরকারী হওয়ার সম্ভাবনা নেই । এমনকি যদি LinkedListএমন কিছু ফাংশন সরবরাহ করা LinkedListNodeথাকে যা কোনও ব্যবহারকারীর LinkedListব্যবহার করতে পারে এমন কোনও বস্তুটিকে ফিরিয়ে দেয় তবে এটি LinkedListNodeকেবল তখনই LinkedListব্যবহারযোগ্য হয়। যে কারণে, "নোড" শ্রেণিকে একটি পিয়ার ক্লাস তৈরি করে LinkedListএটির সমন্বিত সুযোগকে দূষিত করছে।


0
  1. আমি সম্পর্কিত সহায়ক শ্রেণীর জন্য পাবলিক নেস্টেড ক্লাস ব্যবহার করি।

    public class MyRecord {
        // stuff
        public class Comparer : IComparer<MyRecord> {
        }
        public class EqualsComparer : IEqualsComparer<MyRecord> {
        }
    }
    MyRecord[] array;
    Arrays.sort(array, new MyRecord.Comparer());
  2. সম্পর্কিত বৈচিত্রগুলির জন্য এগুলি ব্যবহার করুন।

    // Class that may or may not be mutable.
    public class MyRecord {
        protected string name;
        public virtual String Name { get => name; set => throw new InvalidOperation(); }
    
        public Mutable {
            public override String { get => name; set => name = value; }
        }
    }
    
    MyRecord mutableRecord = new MyRecord.Mutable();

কলকারী কোন সমস্যার জন্য কোন সংস্করণ উপযুক্ত তা চয়ন করতে পারেন। কখনও কখনও একটি ক্লাসে একটি পাসে সম্পূর্ণরূপে নির্মাণ করা যায় না এবং এর জন্য পরিবর্তনীয় সংস্করণ প্রয়োজন। চক্রীয় ডেটা পরিচালনা করার ক্ষেত্রে এটি সর্বদা সত্য। মিউটবেলগুলি কেবল পরে পঠনযোগ্য রূপান্তরিত হতে পারে।

  1. আমি এগুলি অভ্যন্তরীণ রেকর্ডগুলির জন্য ব্যবহার করি

    public class MyClass {
        List<Line> lines = new List<Line>();
    
        public void AddUser( string name, string address ) => lines.Add(new Line { Name = name, Address = address });
    
        class Line { string Name; string Address; }
    }

0

আপনি যখনই ক্লাসের একাধিক উদাহরণ তৈরি করতে চান বা যখনই আপনি এই ধরণের আরও উপলভ্য করতে চান তখন নেস্টেড ক্লাস ব্যবহার করা যেতে পারে।

নেস্টেড ক্লাস এনক্যাপসুলেশনগুলি বাড়ায় পাশাপাশি এটি আরও পঠনযোগ্য এবং রক্ষণাবেক্ষণযোগ্য কোডের দিকে নিয়ে যায়।

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