"অ্যাবস্ট্রাক্ট ওভার" এর অর্থ কী?


95

স্কেল সাহিত্যে প্রায়শই আমি "অ্যাবস্ট্রাক্ট ওভার" শব্দবন্ধটির মুখোমুখি হই, তবে উদ্দেশ্যটি বুঝতে পারি না। উদাহরণস্বরূপ , মার্টিন ওডারস্কি লেখেন

আপনি প্যারামিটার হিসাবে পদ্ধতিগুলি (বা "ফাংশন") পাস করতে পারেন, বা আপনি এগুলি বিমূর্ত করতে পারেন । আপনি পরামিতি হিসাবে প্রকারগুলি নির্দিষ্ট করতে পারেন, বা আপনি সেগুলি বিমূর্ত করতে পারেন ।

অন্য একটি উদাহরণ হিসাবে, "অবজারভার প্যাটার্নটি হ্রাস করা" কাগজে,

আমাদের ইভেন্ট স্ট্রিমের প্রথম শ্রেণির মান হওয়ার ফলস্বরূপ আমরা সেগুলি বিমূর্ত করতে পারি।

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

বিমূর্ত প্রকারের সদস্যরা কংক্রিটের ধরণের উপাদানগুলির উপর বিমূর্ত করার নমনীয় উপায় সরবরাহ করে ।

এমনকি প্রাসঙ্গিক স্ট্যাক ওভারফ্লো প্রশ্নগুলিও এই পরিভাষাটি ব্যবহার করে। "প্যারামিটারাইজড টাইপের উপর অস্তিত্বের বিমূর্ততা দিতে পারে না ..."

সুতরাং ... "অ্যাবস্ট্রাক্ট ওভার" এর অর্থ কী?

উত্তর:


124

বীজগণিতকালে, যেমন প্রতিদিনের ধারণা গঠনের মতো বিমূর্ততা কিছু প্রয়োজনীয় বৈশিষ্ট্য দ্বারা জিনিসগুলিকে গোষ্ঠীকরণ এবং তাদের নির্দিষ্ট অন্যান্য বৈশিষ্ট্যগুলি বাদ দিয়ে তৈরি হয়। বিমূর্ততাটি একটি একক প্রতীক বা শব্দের অধীনে একীভূত হয়েছে যা মিলগুলি বোঝায়। আমরা বলি যে আমরা পার্থক্যগুলিকে বিমূর্ত করি , তবে এর সত্যিকার অর্থে আমরা মিলগুলি দ্বারা সংহত করছি gra

উদাহরণস্বরূপ, একটি প্রোগ্রাম যা সংখ্যার যোগফল লাগে বিবেচনা 1, 2এবং 3:

val sumOfOneTwoThree = 1 + 2 + 3

এই প্রোগ্রামটি খুব আকর্ষণীয় নয়, যেহেতু এটি খুব বিমূর্ত নয়। একটি সংকেতের অধীনে সংখ্যার সমস্ত তালিকা সংহত করে আমরা সংখ্যার সংখ্যায় সংখ্যার বিমূর্ত করতে পারি ns:

def sumOf(ns: List[Int]) = ns.foldLeft(0)(_ + _)

এবং আমরা বিশেষত যত্ন নিই না যে এটি একটি তালিকাও। তালিকাটি একটি নির্দিষ্ট ধরণের নির্মাতা (একটি প্রকার গ্রহণ করে এবং একটি প্রকার ফেরত দেয়) তবে আমরা কোন প্রয়োজনীয় বৈশিষ্ট্যটি (যা এটি ভাঁজ করা যেতে পারে) তা উল্লেখ করে প্রকার নির্মাতার উপর বিমূর্ত করতে পারি:

trait Foldable[F[_]] {
  def foldl[A, B](as: F[A], z: B, f: (B, A) => B): B
}

def sumOf[F[_]](ns: F[Int])(implicit ff: Foldable[F]) =
  ff.foldl(ns, 0, (x: Int, y: Int) => x + y)

এবং আমাদের অন্তর্ভুক্ত Foldableউদাহরণ থাকতে পারে Listএবং অন্য কোনও জিনিস যা আমরা ভাঁজ করতে পারি।

implicit val listFoldable = new Foldable[List] {
  def foldl[A, B](as: List[A], z: B, f: (B, A) => B) = as.foldLeft(z)(f)
}

val sumOfOneTwoThree = sumOf(List(1,2,3))

আরও কী, আমরা অপারেশন এবং অপারেশনগুলির ধরণ উভয়কেই বিমূর্ত করতে পারি :

trait Monoid[M] {
  def zero: M
  def add(m1: M, m2: M): M
}

trait Foldable[F[_]] {
  def foldl[A, B](as: F[A], z: B, f: (B, A) => B): B
  def foldMap[A, B](as: F[A], f: A => B)(implicit m: Monoid[B]): B =
    foldl(as, m.zero, (b: B, a: A) => m.add(b, f(a)))
}

def mapReduce[F[_], A, B](as: F[A], f: A => B)
                         (implicit ff: Foldable[F], m: Monoid[B]) =
  ff.foldMap(as, f)

এখন আমাদের বেশ সাধারণ কিছু আছে। পদ্ধতিটি যে mapReduceকোনও ভাঁজ করবে F[A]যা আমরা প্রমাণ করতে পারি যে Fএটি ভাঁজযোগ্য এবং এটি Aএকটি মনোয়েড বা একটিতে ম্যাপ করা যায়। উদাহরণ স্বরূপ:

case class Sum(value: Int)
case class Product(value: Int)

implicit val sumMonoid = new Monoid[Sum] {
  def zero = Sum(0)
  def add(a: Sum, b: Sum) = Sum(a.value + b.value)
}

implicit val productMonoid = new Monoid[Product] {
  def zero = Product(1)
  def add(a: Product, b: Product) = Product(a.value * b.value)
}

val sumOf123 = mapReduce(List(1,2,3), Sum)
val productOf456 = mapReduce(List(4,5,6), Product)

আমরা মনোয়েড এবং ফোল্ডেবলগুলি বিমূর্ত করে ফেলেছি।


@ কাউব্যাটচেক কোডটি আরপিএল জরিমানা করে। আপনি স্কালার কোন সংস্করণ ব্যবহার করছেন এবং আপনি কোন ত্রুটি পেয়েছেন?
ড্যানিয়েল সি সোব্রাল

4
@ অ্যাপোকালিস্প আপনি দুটি চূড়ান্ত উদাহরণগুলির মধ্যে একটি Setবা অন্য কোনও ভাঁজযোগ্য প্রকার তৈরি করলে এটি আকর্ষণীয় হবে । একটি Stringএবং কনটেন্টেশন সহ একটি উদাহরণও বেশ দুর্দান্ত।
ড্যানিয়েল সি সোব্রাল

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

6
সর্বশেষ 2 লাইনে আপনি যে যোগফল এবং পণ্য সহযোগী বস্তুগুলি প্রয়োগ করেছেন (কারণ) তারা প্রয়োগ (অন্তর্) সংজ্ঞায়িত করেছেন, তাদের স্কেল দ্বারা ইনট => সম এবং ইন্ট => প্রোডাক্ট হিসাবে বিবেচনা করা হবে সে সম্পর্কে আমি এক মুহুর্ত সময় নিয়েছিলাম সংকলক খুব সুন্দর!
ক্রিস নুটি কম্বে

চমৎকার পোস্ট :)! আপনার শেষ উদাহরণে, মনোয়েড অন্তর্নিহিত যুক্তি অপ্রয়োজনীয় বলে মনে হচ্ছে। এটি সহজ: gist.github.com/cvogt/9716490
সিভোগ্ট

11

প্রথম অনুমান হিসাবে, কোনও কিছুর "অ্যাবস্ট্রাক্ট ওভার" সক্ষম হওয়ার অর্থ এই যে কোনও কিছু সরাসরি ব্যবহারের পরিবর্তে আপনি এটির একটি প্যারামিটার তৈরি করতে পারেন, বা অন্যথায় এটি "বেনামে" ব্যবহার করতে পারেন।

স্কেলা আপনাকে ক্লাস, পদ্ধতি এবং মানগুলিকে টাইপ প্যারামিটার এবং মানগুলিকে বিমূর্ত (বা বেনামে) প্রকারের মঞ্জুরি দিয়ে প্রকারভেদগুলিতে বিমূর্ত করতে দেয়।

স্কালা আপনাকে ক্রিয়াকলাপগুলির পরামিতিগুলির পদ্ধতিগুলিকে মঞ্জুরি দিয়ে ক্রিয়া ছাড়াই বিমূর্ত করতে দেয়।

ধরণের কাঠামোগতভাবে সংজ্ঞায়িত করার অনুমতি দিয়ে স্কালা আপনাকে বৈশিষ্ট্যগুলি থেকে বিমূর্ত করতে দেয়।

স্কেল আপনাকে উচ্চতর-অর্ডার প্রকারের পরামিতিগুলিকে অনুমতি দিয়ে টাইপ পরামিতিগুলির উপর বিমূর্ত করতে দেয়।

স্কেলা আপনাকে এক্সট্র্যাক্টর তৈরি করার অনুমতি দিয়ে ডেটা অ্যাক্সেস প্যাটার্নগুলিকে বিমূর্ত করতে দেয়।

স্কেল আপনাকে প্যারামিটার হিসাবে অন্তর্নিহিত রূপান্তরগুলির অনুমতি দিয়ে "" অন্য কিছু হিসাবে ব্যবহার করা যেতে পারে এমন জিনিসগুলির "উপরে বিমূর্ত করতে অনুমতি দেয়। হ্যাসেল টাইপ ক্লাসগুলির সাথে একইভাবে কাজ করে।

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

("টাইপ কনস্ট্রাক্টরদের উপর মনস অ্যাবস্ট্রাক্ট" কেবলমাত্র একটি অত্যন্ত সীমাবদ্ধ উপায়ে সত্য you

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


4
আপনি একটি Manifest, বা এমনকি একটি পাস করতে পারেন Classএবং সেই শ্রেণীর নতুন অবজেক্টগুলিকে ইনস্ট্যান্ট করতে প্রতিবিম্ব ব্যবহার করতে পারেন।
ড্যানিয়েল সি। সোব্রাল

6

বিমূর্ততা হ'ল এক ধরণের সাধারণীকরণ।

http://en.wikedia.org/wiki/Abstration

জটিলতা হ্রাস করার জন্য কেবল স্কেলায় নয় অনেক ভাষায় এই জাতীয় ব্যবস্থা থাকা দরকার (বা কমপক্ষে একটি শ্রেণিবিন্যাস তৈরি করুন যা পার্টিশন সম্পর্কিত তথ্যগুলি টুকরোগুলি বোঝার জন্য সহজ করে তোলে)।

একটি শ্রেণি হ'ল একটি সাধারণ ডেটা ধরণের উপর বিমূর্ততা। এটি একটি প্রাথমিক ধরণের মত ধরণের তবে আসলে এগুলিকে সাধারণীকরণ করে। সুতরাং একটি শ্রেণি একটি সাধারণ ডেটা ধরণের চেয়ে বেশি তবে এর সাথে অনেকগুলি মিল রয়েছে।

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

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

উদাহরণস্বরূপ, যদি আমার কোনও বিশেষ ডেটা টাইপের প্রয়োজন হয় যা কোনও ইন্টার এর মতো ছিল তবে, আমি বলতে পারি যে আমি একটি নতুন টাইপ তৈরি করে এটির উপর বিমূর্ত করতে পারব যা আমার প্রয়োজন মতো বৈশিষ্ট্যযুক্ত ছিল তবে properties আমি এই জাতীয় কাজটি করার জন্য যে প্রক্রিয়াটি ব্যবহার করব এটি "বিমূর্ত" বলা হবে।


5

এখানে আমার সংকীর্ণ শো এবং ব্যাখ্যা বলুন। এটি স্ব-ব্যাখ্যামূলক এবং REPL এ চলে runs

class Parameterized[T] { // type as a parameter
  def call(func: (Int) => Int) = func(1)  // function as a parameter
  def use(l: Long) { println(l) } // value as a parameter
}

val p = new Parameterized[String] // pass type String as a parameter
p.call((i:Int) => i + 1) // pass function increment as a parameter
p.use(1L) // pass value 1L as a parameter


abstract class Abstracted { 
  type T // abstract over a type
  def call(i: Int): Int // abstract over a function
  val l: Long // abstract over value
  def use() { println(l) }
}

class Concrete extends Abstracted { 
  type T = String // specialize type as String
  def call(i:Int): Int = i + 1 // specialize function as increment function
  val l = 1L // specialize value as 1L
}

val a: Abstracted = new Concrete
a.call(1)
a.use()

4
কোড-শক্তিশালী এখনও সংক্ষিপ্তভাবে "অ্যাবস্ট্রাক্ট ওভার" ধারণাটি এই ভাষাটি +1
ব্যবহারকারী 44298

2

অন্যান্য উত্তরগুলি কী ধরণের বিমূর্ততা বিদ্যমান তা ইতিমধ্যে একটি ভাল ধারণা দেয়। একের পর এক উদ্ধৃতিগুলি যেতে দেওয়া যাক এবং একটি উদাহরণ সরবরাহ করুন:

আপনি প্যারামিটার হিসাবে পদ্ধতিগুলি (বা "ফাংশন") পাস করতে পারেন, বা আপনি এগুলি বিমূর্ত করতে পারেন। আপনি পরামিতি হিসাবে প্রকারগুলি নির্দিষ্ট করতে পারেন, বা আপনি সেগুলি বিমূর্ত করতে পারেন।

পরামিতি হিসাবে ফাংশন পাস: List(1,-2,3).map(math.abs(x))স্পষ্টতই absএখানে প্যারামিটার হিসাবে পাস করা হয়। mapনিজেই কোনও ফাংশনকে বিমূর্ত করে তোলে যা প্রতিটি তালিকার উপাদানগুলির সাথে একটি নির্দিষ্ট বিশেষ জিনিস করে। val list = List[String]()একটি ধরণের পরামিতি (স্ট্রিং) নির্দিষ্ট করে। যদি আপনি একটি সংগ্রহে টাইপ যা বিমূর্ত টাইপ সদস্যদের পরিবর্তে ব্যবহার লিখতে পেরেছিলেন: val buffer = Buffer{ type Elem=String }। একটি পার্থক্য হ'ল আপনাকে লিখতে হবে def f(lis:List[String])...তবে def f(buffer:Buffer)..., উপাদান উপাদানটি দ্বিতীয় পদ্ধতিতে "লুকানো" ধরণের।

আমাদের ইভেন্ট স্ট্রিমের প্রথম-শ্রেণীর মান হওয়ার ফলস্বরূপ আমরা সেগুলি বিমূর্ত করতে পারি।

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

বিমূর্ত প্রকারের সদস্যরা কংক্রিটের ধরণের উপাদানগুলির উপর বিমূর্ত করার নমনীয় উপায় সরবরাহ করে।

উপরের বাফার ক্লাসটি এর জন্য ইতিমধ্যে একটি উদাহরণ।


1

উপরের উত্তরগুলি একটি দুর্দান্ত ব্যাখ্যা প্রদান করে তবে এটি একটি বাক্যে সংক্ষেপে বলতে গেলে আমি বলব:

কোনও কিছুর উপরে বিমূর্তি করা যেখানে একে অপ্রাসঙ্গিক তা অবহেলা করার মতোই ।

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