En algèbre, comme dans la formation quotidienne des concepts, les abstractions sont formées en regroupant les choses selon certaines caractéristiques essentielles et en omettant leurs autres caractéristiques spécifiques. L'abstraction est unifiée sous un seul symbole ou mot dénotant les similitudes. Nous disons que nous faisons abstraction des différences, mais cela signifie vraiment que nous intégrons par les similitudes.
Par exemple, envisager un programme qui prend la somme des nombres 1
, 2
et 3
:
val sumOfOneTwoThree = 1 + 2 + 3
Ce programme n'est pas très intéressant, car il n'est pas très abstrait. Nous pouvons faire abstraction des nombres que nous additionnons, en intégrant toutes les listes de nombres sous un seul symbole ns
:
def sumOf(ns: List[Int]) = ns.foldLeft(0)(_ + _)
Et nous ne nous soucions pas particulièrement du fait que ce soit une liste non plus. List est un constructeur de type spécifique (prend un type et retourne un type), mais nous pouvons faire abstraction du constructeur de type en spécifiant la caractéristique essentielle que nous voulons (qu'il puisse être plié):
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)
Et nous pouvons avoir des Foldable
instances implicites pour List
et toute autre chose que nous pouvons replier.
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))
De plus, nous pouvons faire abstraction à la fois de l'opération et du type des opérandes:
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)
Maintenant, nous avons quelque chose d'assez général. La méthode mapReduce
pliera tout élément F[A]
que nous pouvons prouver qu'il F
est pliable et qui A
est un monoïde ou peut être mappé en un seul. Par exemple:
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)
Nous avons résumé les monoïdes et les pliables.
Set
ou un autre type pliable. Un exemple avec uneString
concaténation et serait également assez cool.En première approximation, être capable de «faire abstraction» de quelque chose signifie qu'au lieu d'utiliser ce quelque chose directement, vous pouvez en faire un paramètre, ou autrement l'utiliser «anonymement».
Scala vous permet d'abstraire des types, en autorisant les classes, les méthodes et les valeurs à avoir des paramètres de type et les valeurs à avoir des types abstraits (ou anonymes).
Scala vous permet d'abstraire des actions, en permettant aux méthodes d'avoir des paramètres de fonction.
Scala vous permet d'abstraire des entités, en autorisant la définition structurelle des types.
Scala vous permet d'abstraire des paramètres de type, en autorisant des paramètres de type d'ordre supérieur.
Scala vous permet d'abstraire des modèles d'accès aux données, en vous permettant de créer des extracteurs.
Scala vous permet d'abstraire "des choses qui peuvent être utilisées comme autre chose", en autorisant des conversions implicites comme paramètres. Haskell fait de même avec les classes de types.
Scala ne vous permet pas (encore) d'abstraire des classes. Vous ne pouvez pas passer une classe à quelque chose, puis utiliser cette classe pour créer de nouveaux objets. D'autres langages autorisent l'abstraction sur les classes.
("Monades abstraites sur les constructeurs de types" n'est vrai que de manière très restrictive. Ne restez pas accroché avant d'avoir votre moment "Aha! Je comprends les monades !!".)
La capacité d'abstraction de certains aspects du calcul est essentiellement ce qui permet la réutilisation du code et permet la création de bibliothèques de fonctionnalités. Scala permet d'abstraire beaucoup plus de choses que les langages traditionnels, et les bibliothèques de Scala peuvent être en conséquence plus puissantes.
la source
Manifest
, voire unClass
, et utiliser la réflexion pour instancier de nouveaux objets de cette classe.Une abstraction est une sorte de généralisation.
http://en.wikipedia.org/wiki/Abstraction
Non seulement dans Scala mais dans de nombreux langages, il est nécessaire d'avoir de tels mécanismes pour réduire la complexité (ou au moins créer une hiérarchie qui partitionne les informations en éléments plus faciles à comprendre).
Une classe est une abstraction sur un type de données simple. C'est un peu comme un type de base mais les généralise en fait. Une classe est donc plus qu'un simple type de données, mais a beaucoup de choses en commun avec elle.
Quand il dit «faire abstraction», il veut dire le processus par lequel vous généralisez. Donc, si vous faites abstraction de méthodes en tant que paramètres, vous généralisez le processus pour le faire. par exemple, au lieu de passer des méthodes aux fonctions, vous pouvez créer un type de manière généralisée de le gérer (comme ne pas passer du tout de méthodes mais construire un système spécial pour le gérer).
Dans ce cas, il désigne spécifiquement le processus d'abstraction d'un problème et de création d'une solution de type oop au problème. C a très peu de capacité d'abstraction (vous pouvez le faire mais cela devient très vite compliqué et le langage ne le prend pas directement en charge). Si vous l'avez écrit en C ++, vous pouvez utiliser des concepts oop pour réduire la complexité du problème (enfin, c'est la même complexité mais la conceptualisation est généralement plus facile (au moins une fois que vous apprenez à penser en termes d'abstractions)).
Par exemple, si j'avais besoin d'un type de données spécial qui ressemblait à un int mais, disons restreint, je pourrais faire abstraction dessus en créant un nouveau type qui pourrait être utilisé comme un int mais qui avait les propriétés dont j'avais besoin. Le processus que j'utiliserais pour faire une telle chose s'appellerait un "résumé".
la source
Voici mon spectacle étroit et dire l'interprétation. Il est explicite et fonctionne dans le REPL.
la source
Les autres réponses donnent déjà une bonne idée des types d'abstractions qui existent. Passons en revue les citations une par une et donnons un exemple:
Passer la fonction en tant que paramètre: est
List(1,-2,3).map(math.abs(x))
clairementabs
passé en paramètre ici.map
lui-même fait abstraction d'une fonction qui fait une certaine chose spécialisée avec chaque élément de liste.val list = List[String]()
spécifie un paramètre de type (String). Vous pouvez écrire un type de collection qui utilise les membres de type abstrait à la place:val buffer = Buffer{ type Elem=String }
. Une différence est que vous devez écriredef f(lis:List[String])...
maisdef f(buffer:Buffer)...
, le type d'élément est donc "caché" dans la deuxième méthode.Dans Swing, un événement «arrive» à l'improviste, et vous devez le gérer ici et maintenant. Les flux d'événements vous permettent de faire toute la plomberie et le câblage d'une manière plus déclarative. Par exemple, lorsque vous voulez changer l'auditeur responsable dans Swing, vous devez désenregistrer l'ancien et enregistrer le nouveau, et connaître tous les détails sanglants (par exemple les problèmes de threading). Avec les flux d'événements, la source des événements devient une chose que vous pouvez simplement transmettre, ce qui la rend pas très différente d'un flux d'octets ou de caractères, d'où un concept plus "abstrait".
La classe Buffer ci-dessus en est déjà un exemple.
la source
Les réponses ci-dessus fournissent une excellente explication, mais pour la résumer en une seule phrase, je dirais:
la source