42

抽象化とは、より具体的なものをより抽象的にすることだと理解しています。その何かは、データ構造またはプロシージャのいずれかである可能性があります。例えば:

  1. データの抽象化: 長方形は正方形を抽象化したものです。正方形には 2 組の対辺があるという事実に集中し、正方形の隣接する辺が等しいという事実を無視します。
  2. 手続き型の抽​​象化: 高階関数mapは、値のリストに対して一連の操作を実行して、まったく新しい値のリストを生成する手続きの抽象化です。新しいリストを生成するために、プロシージャがリストのすべての項目をループ処理し、リストのすべての項目に対して実行される実際の操作を無視するという事実に集中します。

だから私の質問はこれです: 抽象化は一般化とどう違うのですか? 主に関数型プログラミングに関連する回答を探しています。ただし、オブジェクト指向プログラミングに類似点がある場合は、それらについても学びたいと思います。

4

8 に答える 8

46

確かに非常に興味深い質問です。このトピックに関する記事を見つけました。簡潔に次のように述べています。

抽象化は無関係な詳細を隠すことで複雑さを軽減しますが、一般化は、同様の機能を実行する複数のエンティティを 1 つの構造に置き換えることで複雑さを軽減します。

図書館の本を管理するシステムの古い例を見てみましょう。本にはたくさんのプロパティ (ページ数、重さ、フォント サイズ、表紙など) がありますが、私たちのライブラリの目的では必要なだけかもしれません。

Book(title, ISBN, borrowed)

ライブラリ内の実際の書籍から抽象化して、アプリケーションのコンテキストで関心のあるプロパティのみを取得しました。


一方、一般化は詳細を削除しようとはしませんが、機能をより広い (より一般的な) 範囲のアイテムに適用できるようにします。StringListジェネリック コンテナーは、その考え方の非常に良い例です。 、などの実装を記述したくないため、( Scalaのように) すべての型に適用されるジェネリックIntListList を記述します。詳細や操作を削除していないため、リストを抽象化していないことに注意してください。すべてのタイプに一般的に適用できるようにしただけです。List[T]

ラウンド2

@dtldarekの答えは本当にとても良い例です! それに基づいて、さらに明確にする可能性のあるコードを次に示します。

私が言ったことを覚えてBookいますか?もちろん、ライブラリには他にも借りることができるものがあります (Borrowableおそらく単語でさえありませんが、これらすべてのオブジェクトのセットを呼び出します:D):

これらのアイテムはすべて、データベースとビジネス ロジックに抽象的な表現があり、おそらくBook. Borrowableさらに、すべての sに共通する特性を定義する場合があります。

trait Borrowable {
    def itemId:Long
}

次に、すべての に適用される一般化されたロジックを記述できますBorrowable(その時点では、それが本か雑誌かは気にしません)。

object Library {
    def lend(b:Borrowable, c:Customer):Receipt = ...
    [...]
}

要約すると、すべての書籍、雑誌、DVD の抽象的な表現をデータベースに保存しました。正確な表現は実行可能でも必要でもないためです。それから私たちは先に進み、言いました

本、雑誌、DVDの貸出は問いません。それはいつも同じプロセスです。

したがって、借りることができるすべてのものを s として定義することにより、アイテムを借りる操作を一般化Borrowableしました。

于 2013-10-10T11:16:14.087 に答える
2

信頼できる/公式のソースに対処していない: Scalaの例

「抽象」を持つ

  trait AbstractContainer[E] { val value: E }

  object StringContainer extends AbstractContainer[String] {
    val value: String = "Unflexible"
  }

  class IntContainer(val value: Int = 6) extends AbstractContainer[Int]

  val stringContainer = new AbstractContainer[String] {
    val value = "Any string"
  }

そして「一般化」

  def specialized(c: StringContainer.type) =
    println("It's a StringContainer: " + c.value)

  def slightlyGeneralized(s: AbstractContainer[String]) =
    println("It's a String container: " + s.value)

  import scala.reflect.{ classTag, ClassTag }
  def generalized[E: ClassTag](a: AbstractContainer[E]) =
    println(s"It's a ${classTag[E].toString()} container: ${a.value}")

  import scala.language.reflectiveCalls
  def evenMoreGeneral(d: { def detail: Any }) =
    println("It's something detailed: " + d.detail)

実行中

  specialized(StringContainer)
  slightlyGeneralized(stringContainer)
  generalized(new IntContainer(12))
  evenMoreGeneral(new { val detail = 3.141 })

につながる

It's a StringContainer: Unflexible
It's a String container: Any string
It's a Int container: 12
It's something detailed: 3.141
于 2013-10-18T13:52:27.920 に答える
2

抽象化

抽象化は、フレームワークを指定し、実装レベルの情報を隠しています。具体性は抽象化の上に構築されます。詳細を実装する際に従うべき青写真を提供します。抽象化は、低レベルの詳細を隠すことで複雑さを軽減します。

例: 車のワイヤー フレーム モデル。

一般化

汎化は、特殊化から汎化クラスへの「is-a」関係を使用します。特殊化されたクラスから一般化されたクラスまで、共通の構造と動作が使用されます。非常に広いレベルでは、これを継承として理解できます。私が継承という用語を使用する理由は、この用語を非常によく関連付けることができるからです。一般化は「Is-a」関係とも呼ばれます。

例: Person という名前のクラスが存在するとします。学生は人です。学部は人です。したがって、ここでは学生と人間、同様に教員と人間の関係は一般化されています。

于 2013-10-19T18:49:08.007 に答える
0

抽象化とは、通常、不要な詳細を排除して複雑さを軽減することです。たとえば、OOP の抽象クラスは、その子の共通機能を含む親クラスですが、正確な機能を指定していません。

一般化では、必ずしも詳細を避ける必要はありませんが、同じ関数を別の引数に適用できるメカニズムが必要です。たとえば、関数型プログラミング言語の多相型を使用すると、引数に煩わされることなく、関数の操作に集中できます。同様に、Java では、機能が同じであるにもかかわらず、すべての型の「傘」であるジェネリック型を使用できます。

于 2013-10-19T16:31:30.457 に答える