ক্লাস বনাম বস্তু ইন্টারফেস টাইপ করুন


33

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

উদাহরণস্বরূপ, আমার যদি টাইপ ক্লাস থাকে (হাস্কেল সিনট্যাক্সে)

class Functor f where
  fmap :: (a -> b) -> f a -> f b

ইন্টারফেসের চেয়ে এটি কীভাবে আলাদা [1] (জাভা সিনট্যাক্সে)

interface Functor<A> {
  <B> Functor<B> fmap(Function<B, A> fn)
}

interface Function<Return, Argument> {
  Return apply(Argument arg);
}

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

আমি কী মিস করছি?

[1] নোটটি একটি ওও ভাষা দেওয়ার কারণে f aথেকে আর্গুমেন্টটি সরিয়ে ফেলা হয়েছে তা নোট করুন fmap, আপনি কোনও অবজেক্টে এই পদ্ধতিটি কল করছেন calling এই ইন্টারফেসটি ধরে নিয়েছে f aআর্গুমেন্টটি ঠিক করা হয়েছে।

উত্তর:


46

তাদের মৌলিক ফর্মে, টাইপ ক্লাসগুলি কিছুটা অবজেক্ট ইন্টারফেসের সাথে সমান। যাইহোক, অনেক ক্ষেত্রে, তারা অনেক বেশি সাধারণ।

  1. প্রেরণটি মানগুলিতে নয়, প্রকারভেদে রয়েছে। এটি সম্পাদন করার জন্য কোনও মূল্য প্রয়োজন হয় না। উদাহরণস্বরূপ, হাস্কেলের Readক্লাসের মতো ফাংশনের ফলাফলের প্রকারে প্রেরণ করা সম্ভব :

    class Read a where
      readsPrec :: Int -> String -> [(a, String)]
      ...
    

    এই ধরনের প্রেরণ প্রচলিত ওওতে স্পষ্টত অসম্ভব।

  2. ধরণের ক্লাসগুলি প্রাকৃতিকভাবে একাধিক পরামিতি সরবরাহ করে একাধিক প্রেরণে প্রসারিত হয়:

    class Mul a b c where
      (*) :: a -> b -> c
    
    instance Mul Int Int Int where ...
    instance Mul Int Vec Vec where ...
    instance Mul Vec Vec Int where ...
    
  3. দৃষ্টান্ত সংজ্ঞাগুলি উভয় শ্রেণি এবং প্রকার সংজ্ঞা থেকে স্বতন্ত্র, যা তাদের আরও মডিউল করে তোলে। মডিউল A থেকে একটি টাইপ টি মডিউল এম 3-তে কোনও উদাহরণ সরবরাহ না করে মডিউল এম 2 থেকে একটি শ্রেণি সিতে পুনরায় প্রিন্ট করা যেতে পারে। ওওতে, এর জন্য এক্সটেনশন পদ্ধতির মতো আরও বিশেষত্বযুক্ত (এবং কম ওও-ইশ) ভাষার বৈশিষ্ট্য প্রয়োজন।

  4. টাইপ ক্লাসগুলি প্যারামেট্রিক পলিমারফিজমের উপর ভিত্তি করে, সাব টাইপিং নয় not এটি আরও সঠিক টাইপিং সক্ষম করে। যেমন বিবেচনা করুন

    pick :: Enum a => a -> a -> a
    pick x y = if fromEnum x == 0 then y else x
    

    বনাম

    pick(x : Enum, y : Enum) : Enum = if x.fromEnum() == 0 then y else x
    

    পূর্ববর্তী ক্ষেত্রে, প্রয়োগের pick '\0' 'x'ধরন রয়েছে Char, তবে পরবর্তী ক্ষেত্রে, ফলাফল সম্পর্কে আপনারা যা জানতেন তা হ'ল এটি একটি এনুম। (এই কারণেই বেশিরভাগ ওও ভাষাগুলি প্যারামেট্রিক পলিমারফিজমকে একীভূত করার কারণও রয়েছে is)

  5. ঘনিষ্ঠভাবে সম্পর্কিত বাইনারি পদ্ধতি ইস্যু। এগুলি ধরণের শ্রেণীর সাথে সম্পূর্ণ প্রাকৃতিক:

    class Ord a where
      (<) :: a -> a -> Bool
      ...
    
    min :: Ord a => a -> a -> a
    min x y = if x < y then x else y
    

    একাই সাবটাইপিংয়ের মাধ্যমে Ordইন্টারফেসটি প্রকাশ করা অসম্ভব। এটি সঠিকভাবে করতে আপনার আরও জটিল, পুনরাবৃত্ত হওয়া ফর্ম বা প্যারাম্যাট্রিক পলিমারফিজম প্রয়োজন। জাভা Comparableএবং এর ব্যবহারের সাথে তুলনা করুন :

    interface Comparable<T> {
      int compareTo(T y);
    };
    
    <T extends Comparable<T>> T min(T x, T y) {
      if (x.compareTo(y) < 0)
        return x;
      else
        return y;
    }
    

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


আহ, এটা অনেক বোঝায়। টাইম বনাম মান-ভিত্তিক প্রেরণ সম্ভবত আমি যে জিনিসটি সঠিকভাবে ভাবছিলাম তা সম্ভবত নয়। প্যারামেট্রিক পলিমারফিজম এবং আরও নির্দিষ্ট টাইপিংয়ের বিষয়টি বোঝা যায়। আমি সবেমাত্র এটি এবং সাব টাইপিং-ভিত্তিক ইন্টারফেসগুলি একসাথে মনে মনে টেনেছি (স্পষ্টতই আমি জাভাতে মনে করি: - /)।
oconnor0

অস্তিত্বের ধরণগুলি কি নিম্নরূপের Cউপস্থিতি ছাড়াই উপপ্রকার তৈরির অনুরূপ কিছু ?
oconnor0

ধরনের। এগুলি কোনও প্রকারের বিমূর্ততা তৈরির মাধ্যম, অর্থাৎ এর উপস্থাপনাটি গোপন করে iding হাসকেলে, আপনি যদি এর সাথে শ্রেণিক বাধাও সংযুক্ত করেন তবে আপনি এখনও এই শ্রেণীর সমস্ত পদ্ধতি ব্যবহার করতে পারেন, তবে অন্য কিছু নয়। - ডাউনকাস্টগুলি আসলে এমন একটি বৈশিষ্ট্য যা সাবটাইপিং এবং অস্তিত্বের পরিমাণ উভয় থেকে পৃথক, এবং নীতিগতভাবে, পরবর্তীগুলির উপস্থিতিতেও যোগ করা যেতে পারে। ঠিক যেমন ওও ভাষা আছে যারা এটি সরবরাহ করে না।
Andreas রসবার্গ

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

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

6

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

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

ক্লাস টাইপ করার চেয়ে অবজেক্ট ইন্টারফেসগুলি স্ট্যান্ডার্ড এমএল স্বাক্ষরের সাথে বেশি মিল।


এবং এখনও এমএল মডিউল এবং হাস্কেল প্রকারের ক্লাসগুলির মধ্যে একটি ঘনিষ্ঠ সম্পর্ক রয়েছে বলে মনে হয়। cse.unsw.edu.au/~chak/papers/DHC07.html
স্টিভেন শ

1

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

Maybe<Int> val = new Maybe<Int>(5);
Functor<Int> res = val.fmap(someFunctionHere);

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


আমি মনে করি এই সমস্যাটি জাভা উচ্চতর ধরণের প্রকারকে সমর্থন না করার কারণে এবং ইন্টারফেসের সাথে সম্পর্কিত নয় টাইপক্লাসের আলোচনার সাথে। জাভা যদি উচ্চতর ধরণের থাকে তবে fmap খুব ভালভাবে ফিরে আসতে পারে Maybe<Int>
ডিসট্রো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.