0Pricing
Scala for Backend Engineering & Functional Programming · Ders

Varyans: Kovaryans ve Kontravaryans

Genel türlerdeki alt tür ilişkilerini doğru biçimde ele almak için kovaryans ve kontravaryansta uzmanlaşın.

Varyans: Kovaryans ve Kontravaryans, CoddyKit'te ücretsiz bir Scala for Backend Engineering & Functional Programming dersidir. Bu, 3 dersinin 2. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Scala for Backend Engineering & Functional Programming öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Scala for Backend Engineering & Functional Programming kursu toplamda 3 dersten oluşur.

Tür Varyansı Nedir?

Scala'da bir tür hiyerarşiniz olduğunda (ör. Cat, Animal'ın bir alt türüdür), genel türler nasıl davranır?

Bir List[Cat], List[Animal]'ın bir alt türü sayılır mı? Varsayılan olarak her zaman sayılmaz!

Tür varyansı, alt tür ilişkilerinin genel türler için nasıl korunduğunu (veya tersine çevrildiğini) tanımlamamızı sağlar. Bu, esnek ve tür güvenli kod yazmak için çok önemlidir.

Kovaryans: 'Producer' Türleri (+T)

Kovaryans, tür parametresinin önüne + yerleştirilerek gösterilir (ör. trait Box[+T]).

  • A, B'nin bir alt türüyse Box[A], Box[B]'nin bir alt türü olur.
  • Kovaryant türleri T üreten yapılar olarak düşünebilirsiniz. Bunlar yalnızca çıktı konumlarında (yöntemlerin dönüş türleri gibi) kullanılabilir.
  • Bu nedenle Box[Animal] beklediğiniz yerde Box[Cat] sağlayabilirsiniz; çünkü daha özel bir şey üretir (Cat, bir Animal'dır).

Uygulamada Kovaryans

Kovaryant bir Producer trait örneğini çalıştırmayı deneyin:

class Animal
class Cat extends Animal

trait Producer[+T] {
  def produce: T // Output position
}

class CatProducer extends Producer[Cat] {
  def produce: Cat = new Cat
}

object Main {
  def main(args: Array[String]): Unit = {
    val catProducer: Producer[Cat] = new CatProducer
    // Because Producer is covariant, Producer[Cat] is a subtype of Producer[Animal]
    val animalProducer: Producer[Animal] = catProducer 
    println("Assigned CatProducer to AnimalProducer.")
    println(s"Produced: ${animalProducer.produce.getClass.getSimpleName}")
  }
}

Kovaryans Ne Zaman Kullanılır?

Kovaryans, genel türünüz yalnızca T türünde değerler ürettiğinde veya T'yi hiçbir zaman bağımsız değişken olarak kabul etmediğinde güvenlidir.

  • List[+T] gibi değişmez koleksiyonlar bunun en iyi örneklerindendir. Bir List[Cat] yapısını List[Animal] olarak değerlendirebilirsiniz; çünkü ondan yalnızca Animal değerleri (veya bunların alt türlerini) 'okursunuz'.
  • List[Animal] olarak türlendirilmişse bir List[Cat]'e rastgele bir Animal ekleyemezsiniz; bu da tür güvenliğini korur.

Kontravaryans: 'Consumer' Türleri (-T)

Kontravaryans, tür parametresinin önüne - yerleştirilerek gösterilir (ör. trait Consumer[-T]).

  • A, B'nin bir alt türüyse Consumer[B], Consumer[A]'nın bir alt türü olur.
  • Kontravaryant türleri T tüketen yapılar olarak düşünebilirsiniz. Bunlar yalnızca girdi konumlarında (yöntemlerin parametre türleri gibi) kullanılabilir.
  • Bu nedenle Consumer[Cat] beklediğiniz yerde Consumer[Animal] sağlayabilirsiniz; çünkü daha genel bir şeyi tüketir (bir Cat dâhil her Animal'ı işleyebilir).

Uygulamada Kontravaryans

Kontravaryant bir Consumer trait örneğini çalıştırmayı deneyin:

class Animal
class Cat extends Animal

trait Consumer[-T] {
  def consume(item: T): Unit // Input position
}

class AnimalConsumer extends Consumer[Animal] {
  def consume(item: Animal): Unit = {
    println(s"Consumed an animal: ${item.getClass.getSimpleName}")
  }
}

object Main {
  def main(args: Array[String]): Unit = {
    val animalConsumer: Consumer[Animal] = new AnimalConsumer
    // Because Consumer is contravariant, Consumer[Animal] is a subtype of Consumer[Cat]
    val catConsumer: Consumer[Cat] = animalConsumer 
    catConsumer.consume(new Cat)
    println("Assigned AnimalConsumer to CatConsumer.")
  }
}

Kontravaryans Ne Zaman Kullanılır?

Kontravaryans, genel türünüz yalnızca T türündeki değerleri tükettiğinde veya hiçbir zaman T döndürmediğinde güvenlidir.

  • Yaygın bir örnek, özellikle girdi parametresi türü olmak üzere işlevlerdir. Herhangi bir Animal'ı işleyebilen bir işlev (Animal => Unit), elbette bir Cat'ı da işleyebilir. Bu nedenle (Animal => Unit), (Cat => Unit)'in bir alt türüdür.
  • Bu, işlevleri bağımsız değişken olarak aktarırken daha fazla esneklik sağlar.

Değişmezlik: Varsayılan Davranış

+ veya - belirtmezseniz tür parametresi değişmez olur. Scala'da varsayılan davranış budur.

  • Box[A], yalnızca A ile B tam olarak aynı türse Box[B]'nin alt türüdür.
  • Bu, farklı alt türleri hem okuyup hem yazabildiğiniz için tür güvenliği sorunlarını önlemek amacıyla değiştirilebilir koleksiyonlar (ör. Array[T]) için çoğu zaman gereklidir.
class Food
class Apple extends Food

// Invariant Box
class Box[T](val item: T) {
  def getContent: T = item
}

object Main {
  def main(args: Array[String]): Unit = {
    val appleBox = new Box(new Apple)
    // The following line would cause a compile error:
    // val foodBox: Box[Food] = appleBox 
    println(s"An Apple Box contains: ${appleBox.getContent.getClass.getSimpleName}")
    println("Box[Apple] is NOT a subtype of Box[Food] (invariant).")
    println("The types must match exactly for invariant types.")
  }
}

İşlevler: Hem Kovaryant Hem Kontravaryant

Scala'nın işlev türleri olan Function1[-A, +B], her iki varyans türünü zarif bir şekilde birleştirir:

  • Girdi parametresi A kontravaryanttır (-A). Bu, daha genel bir türü (ör. Animal) kabul eden bir işlevin, daha özel bir türü (ör. Cat) kabul eden bir işlevin beklendiği yerde kullanılabileceği anlamına gelir.
  • Dönüş türü B kovaryanttır (+B). Bu, daha özel bir tür (ör. Cat) döndüren bir işlevin, daha genel bir tür (ör. Animal) döndüren bir işlevin beklendiği yerde kullanılabileceği anlamına gelir.
class Vehicle
class Car extends Vehicle

object Main {
  def main(args: Array[String]): Unit = {
    // Contravariance for input: (Vehicle => Unit) is a subtype of (Car => Unit)
    val printVehicle: Vehicle => Unit = (v: Vehicle) => println(s"Printing vehicle: ${v.getClass.getSimpleName}")
    val printCar: Car => Unit = printVehicle // OK: A general printer can print a specific car
    printCar(new Car)

    // Covariance for output: (() => Car) is a subtype of (() => Vehicle)
    val getCar: () => Car = () => new Car
    val getVehicle: () => Vehicle = getCar // OK: A specific producer can fulfill a general request
    println(s"Got vehicle: ${getVehicle().getClass.getSimpleName}")
  }
}

Hızlı Kontrol: Varyans Kuralları

Aşağıdaki trait'i inceleyin:

trait Handler[T] {
  def handle(item: T): Unit
}

Handler[Animal]'ın, Handler[Cat]'ın beklendiği yerde kullanılabilmesi için (Cat, Animal'ı genişletirken) T hangi varyans ekine sahip olmalıdır?

Tekrar: Varyansta Ustalaşma

Scala'da varyans konusunda ustalaştınız! Kısaca tekrar edelim:

  • Kovaryans (+T): Container[Subtype]'ın Container[Supertype]'ın alt türü olmasını sağlar. Yalnızca T döndüren 'üretici' türler için kullanışlıdır.
  • Kontravaryans (-T): Container[Supertype]'ın Container[Subtype]'ın alt türü olmasını sağlar. Girdi olarak yalnızca T kabul eden 'tüketici' türler için kullanışlıdır.
  • Değişmezlik: Varsayılan davranıştır. Türler tam olarak eşleşmelidir.

Varyansı anlamak, Scala'da daha esnek ve tür güvenli genel kod oluşturmanıza yardımcı olur!

Sıkça Sorulan Sorular

“Varyans: Kovaryans ve Kontravaryans” dersi ücretsiz mi?

Evet — “Varyans: Kovaryans ve Kontravaryans” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Scala for Backend Engineering & Functional Programming kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Scala for Backend Engineering & Functional Programming kursu toplamda 3 dersten oluşur.

“Varyans: Kovaryans ve Kontravaryans” dersinde ne öğreneceğim?

Genel türlerdeki alt tür ilişkilerini doğru biçimde ele almak için kovaryans ve kontravaryansta uzmanlaşın. Scala for Backend Engineering & Functional Programming ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

Scala for Backend Engineering & Functional Programming öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te Scala for Backend Engineering & Functional Programming, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 3 dersinin 2. dersidir.

“Varyans: Kovaryans ve Kontravaryans” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu Scala for Backend Engineering & Functional Programming dersinde kod yazıp çalıştırabilir miyim?

Evet. Her Scala for Backend Engineering & Functional Programming dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Jenerikler ve Tür Parametreleri
  2. Varyans: Kovaryans ve Kontravaryans
  3. Tür Sınıfları ve Örtükler
← Scala for Backend Engineering & Functional Programming Sayfasına Dön