Menu
CoddyTech

Çok Biçimlilik

Coddy'nin Ruby Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 32 / 57.

Çok biçimlilik, bir yöntem çağrısının farklı sınıflardaki nesnelerde çalışması ve her nesnenin kendi biçiminde yanıt vermesi anlamına gelir. Şekiller üzerinde döngü oluşturan kod, her birinin ne tür bir şekil olduğunu sormadan area yöntemini çağırır:

class Shape
  def to_s
    format("%s %.2f", self.class.name.downcase, area)
  end
end

class Circle < Shape
  def initialize(r)
    @r = r
  end

  def area
    3.14159 * @r * @r
  end
end

class Square < Shape
  def initialize(side)
    @side = side
  end

  def area
    @side * @side
  end
end

shapes = [Circle.new(1), Square.new(3)]
shapes.each { |s| puts s }
puts format("total %.2f", shapes.sum(&:area))

Çıktı:

circle 3.14
square 9.00
total 12.14

Çok biçimlilik olmadan, çağıran taraf her nesnenin türünü kontrol etmek ve farkın önemli olduğu her yerde bu kontrolü tekrarlamak zorundadır. Çok biçimlilikle birlikte, fark her sınıfın içinde yer alır:

# polimorfizm olmadan
case shape.kind
when "circle" then 3.14159 * shape.r ** 2
when "square" then shape.side ** 2
end

# polimorfizm ile
shape.area

Yeni bir nesne türü eklemek, çağıran kodda değişiklik yapmayı gerektirmez: kendi area metoduna sahip yeni bir alt sınıf, mevcut tüm döngülerde çalışır:

class Shape
  def describe
    "area #{area}"
  end
end

class Square < Shape
  def area
    4
  end
end

class Triangle < Shape
  def area
    6
  end
end

[Square.new, Triangle.new].each { |s| puts s.describe }

Çıktı:

area 4
area 6

to_s günlük bir örnektir: puts bunu herhangi bir nesne üzerinde çağırır ve her sınıf farklı yanıt verir. Kendi to_s yöntemlerini tanımlayarak sınıflarınız da buna katılır:

class Coin
  def to_s
    "a coin"
  end
end

[42, "text", nil, [1, 2], Coin.new].each { |x| puts "[#{x}]" }

Çıktı:

[42]
[text]
[]
[[1, 2]]
[a coin]
challenge icon

Görev

Kolay

Şekilleri tamamla. Shape#to_s, circle: 3.14 değerini döndürür: sınıf adının küçük harfli hâli ve iki ondalık basamaklı alan; her alt sınıf area metodunu sağlar: Circle.new(r) (pi için 3.14159 kullan), Rectangle.new(w, h) ve Triangle.new(base, height).

Verilen kod circle 1, rectangle 2 3 veya triangle 4 5 satırlarını okur, her şekli yazdırır, ardından total: 22.14 ve largest: rectangle: 6.00 değerlerini yazdırır; yalnızca to_s ve area kullanır.

Kodunu shape.rb, circle.rb, rectangle.rb ve triangle.rb dosyalarına yaz. main.rb, verilen girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

require_relative 'shape'
require_relative 'circle'
require_relative 'rectangle'
require_relative 'triangle'

# Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
input = []
while (line = gets)
  input << line.chomp
end
kinds = { "circle" => Circle, "rectangle" => Rectangle, "triangle" => Triangle }
shapes = input.map do |line|
  kind, *numbers = line.split
  kinds[kind].new(*numbers.map(&:to_f))
end
shapes.each { |s| puts s }
puts format("total: %.2f", shapes.sum(&:area))
puts "largest: #{shapes.max_by(&:area)}"
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online Ruby derleyicisi