Dalam aljabar, seperti dalam pembentukan konsep sehari-hari, abstraksi dibentuk dengan mengelompokkan hal-hal berdasarkan beberapa karakteristik esensial dan menghilangkan karakteristik spesifik lainnya. Abstraksi disatukan di bawah satu simbol atau kata yang menunjukkan kesamaan. Kami mengatakan bahwa kami mengabstraksikan perbedaan, tetapi ini benar-benar berarti kami terintegrasi oleh kesamaan.
Sebagai contoh, mempertimbangkan program yang mengambil jumlah dari angka 1
, 2
dan 3
:
val sumOfOneTwoThree = 1 + 2 + 3
Program ini tidak terlalu menarik, karena tidak terlalu abstrak. Kita dapat mengabstraksi bilangan yang kita jumlahkan, dengan mengintegrasikan semua daftar bilangan di bawah satu simbol ns
:
def sumOf(ns: List[Int]) = ns.foldLeft(0)(_ + _)
Dan kami juga tidak terlalu peduli bahwa itu adalah Daftar. List adalah konstruktor tipe tertentu (mengambil tipe dan mengembalikan tipe), tetapi kita bisa mengabstraksi konstruktor tipe dengan menentukan karakteristik penting mana yang kita inginkan (yang dapat dilipat):
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)
Dan kita dapat memiliki Foldable
contoh implisit untuk List
dan hal lain yang dapat kita lipat.
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))
Terlebih lagi, kita dapat mengabstraksi operasi dan jenis operan:
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)
Sekarang kami memiliki sesuatu yang cukup umum. Metode ini mapReduce
akan melipat apa pun F[A]
yang kita dapat buktikan bahwa F
dapat dilipat dan itu A
adalah monoid atau dapat dipetakan menjadi satu. Sebagai contoh:
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)
Kami telah mengabstraksi monoid dan lipat.
Set
atau jenis lipat lainnya. Contoh denganString
dan penggabungan juga akan cukup keren.Untuk perkiraan pertama, kemampuan untuk "mengabstraksikan" sesuatu berarti bahwa alih-alih menggunakan sesuatu itu secara langsung, Anda dapat membuat parameternya, atau menggunakannya "secara anonim".
Scala memungkinkan Anda untuk mengabstraksi tipe, dengan mengizinkan kelas, metode, dan nilai memiliki parameter tipe, dan nilai memiliki tipe abstrak (atau anonim).
Scala memungkinkan Anda untuk mengabstraksi tindakan, dengan mengizinkan metode memiliki parameter fungsi.
Scala memungkinkan Anda untuk mengabstraksi fitur, dengan mengizinkan tipe untuk didefinisikan secara struktural.
Scala memungkinkan Anda untuk mengabstraksi parameter tipe, dengan mengizinkan parameter tipe orde tinggi.
Scala memungkinkan Anda untuk mengabstraksi pola akses data, dengan memungkinkan Anda membuat ekstraktor.
Scala memungkinkan Anda untuk mengabstraksi "hal-hal yang dapat digunakan sebagai sesuatu yang lain", dengan mengizinkan konversi implisit sebagai parameter. Haskell melakukan hal yang sama dengan kelas tipe.
Scala tidak (belum) memungkinkan Anda untuk mengabstraksi kelas. Anda tidak bisa meneruskan kelas ke sesuatu, lalu menggunakan kelas itu untuk membuat objek baru. Bahasa lain mengizinkan abstraksi atas kelas.
("Monads abstrak atas konstruktor tipe" hanya benar dalam cara yang sangat terbatas. Jangan terpaku padanya sampai Anda memiliki momen "Aha! Saya mengerti monads !!".)
Kemampuan untuk mengabstraksi beberapa aspek komputasi pada dasarnya adalah yang memungkinkan penggunaan kembali kode, dan memungkinkan pembuatan pustaka fungsionalitas. Scala memungkinkan lebih banyak jenis hal untuk diabstraksi daripada bahasa yang lebih umum, dan perpustakaan di Scala dapat menjadi lebih kuat.
sumber
Manifest
, atau bahkan aClass
, dan menggunakan refleksi untuk membuat instance objek baru dari kelas itu.Abstraksi adalah semacam generalisasi.
http://en.wikipedia.org/wiki/Abstraction
Tidak hanya di Scala tetapi banyak bahasa ada kebutuhan untuk memiliki mekanisme seperti itu untuk mengurangi kompleksitas (atau setidaknya membuat hierarki yang membagi informasi menjadi bagian yang lebih mudah dipahami).
Kelas adalah abstraksi atas tipe data sederhana. Ini seperti tipe dasar tetapi sebenarnya menggeneralisasikannya. Jadi kelas lebih dari sekedar tipe data sederhana tetapi memiliki banyak kesamaan dengannya.
Ketika dia mengatakan "mengabstraksi" yang dia maksud adalah proses yang Anda gunakan untuk menggeneralisasi. Jadi, jika Anda mengabstraksi metode sebagai parameter, Anda menggeneralisasi proses untuk melakukannya. misalnya, alih-alih meneruskan metode ke fungsi, Anda mungkin membuat beberapa jenis cara umum untuk menanganinya (seperti tidak meneruskan metode sama sekali tetapi membangun sistem khusus untuk menghadapinya).
Dalam hal ini yang dimaksud secara khusus adalah proses mengabstraksi masalah dan menciptakan solusi seperti oop untuk masalah tersebut. C memiliki kemampuan yang sangat sedikit untuk mengabstraksi (Anda dapat melakukannya tetapi menjadi sangat cepat berantakan dan bahasa tidak mendukungnya secara langsung). Jika Anda menulisnya dalam C ++, Anda dapat menggunakan konsep oop untuk mengurangi kompleksitas masalah (yah, kompleksitasnya sama tetapi konseptualisasi umumnya lebih mudah (setidaknya setelah Anda belajar berpikir dalam kerangka abstraksi)).
misalnya, Jika saya membutuhkan tipe data khusus yang seperti int tetapi, katakanlah dibatasi, saya dapat mengabstraksikannya dengan membuat tipe baru yang dapat digunakan seperti int tetapi memiliki properti yang saya butuhkan. Proses yang akan saya gunakan untuk melakukan hal seperti itu akan disebut "abstrak".
sumber
Ini adalah pertunjukan sempit saya dan tafsirkan interpretasi. Ini cukup jelas dan berjalan di REPL.
sumber
Jawaban yang lain sudah memberikan gambaran yang baik tentang jenis abstraksi yang ada. Mari kita bahas kutipan satu per satu, dan berikan contoh:
Lulus fungsi sebagai parameter:
List(1,-2,3).map(math.abs(x))
Jelasabs
dilewatkan sebagai parameter di sini.map
itu sendiri mengabstraksi fungsi yang melakukan hal khusus tertentu dengan setiap elemen daftar.val list = List[String]()
menentukan tipe paramter (String). Anda bisa menulis jenis koleksi yang menggunakan anggota jenis abstrak sebagai gantinya:val buffer = Buffer{ type Elem=String }
. Satu perbedaan adalah Anda harus menulisdef f(lis:List[String])...
tetapidef f(buffer:Buffer)...
, jadi tipe elemennya agak "tersembunyi" dalam metode kedua.Dalam Swing, sebuah peristiwa "terjadi" begitu saja, dan Anda harus menanganinya di sini dan saat ini. Aliran acara memungkinkan Anda melakukan semua pemipaan kabel dengan cara yang lebih deklaratif. Misalnya, saat Anda ingin mengubah pendengar yang bertanggung jawab di Swing, Anda harus membatalkan pendaftaran yang lama dan mendaftarkan yang baru, dan mengetahui semua detail yang mengerikan (misalnya masalah threading). Dengan aliran acara, sumber acara menjadi sesuatu yang dapat Anda sebarkan begitu saja, membuatnya tidak jauh berbeda dari aliran byte atau char, oleh karena itu konsepnya lebih "abstrak".
Kelas Buffer di atas sudah menjadi contoh untuk ini.
sumber
Jawaban di atas memberikan penjelasan yang sangat bagus, tetapi untuk meringkasnya dalam satu kalimat, saya akan mengatakan:
sumber