Yan yana
Soyut SınıfvsInterface
Soyut sınıf ile interface arasındaki fark nedir?
Güncellendi 2 dk okuma8 fark
Kısaca
Soyut sınıf, alt sınıflarıyla kod ve durum paylaşır; interface ise yalnızca bir türün neler yapabildiğini bildirir ve bir sınıf birçoğunu uygulayabilir.
Soyut Sınıf
Soyut sınıf, tek başına örneklenemeyen bir sınıftır; alt sınıflarıyla kod paylaşır ve her alt sınıfın gerçekleştirmesi gereken metotları bildirir.
Soyut Sınıf sayfasını okuInterface
Arayüz
Interface, bir türün sağlamayı vaat ettiği metot ve özellik imzalarından oluşan adlandırılmış bir kümedir; bu üyelerin nasıl gerçekleştirildiğini söylemez.
Interface sayfasını okuSoyut Sınıf ve Interface karşılaştırması
| Özellik | Soyut Sınıf | Interface |
|---|---|---|
| Amacı | İlişkili sınıflar arasında kod ve durum paylaşmak | Bir türün neler yapabildiğini tarif etmek |
| Sınıf başına | Bir tane (Java, C# ve TypeScript'te) | Gerektiği kadar |
| Metotlar | Soyut metotlar ve eksiksiz yazılmış metotlar | İmzalar; Java 8 ve C# 8'den beri varsayılan gövdeler |
| Alanlar | Kendi değerleri olan örnek alanları | Örnek durumu yok; en fazla sabitler ya da özellik bildirimleri |
| Yapıcı metot | Var; alt sınıflar onu super ile çağırır | Yok |
| Üye erişimi | protected ve private üyeler kullanabilir | Üyeler varsayılan olarak public'tir |
| İlişki | “-dir” (is-a): bir Circle bir Shape'tir | “yapabilir” (can-do): bir Circle Printable'dır |
| TypeScript'te çalışma zamanında | Gerçek bir JavaScript sınıfına derlenir | Silinir; yalnızca tip denetimi için vardır |
Fark, açıklamalı
Soyut sınıf, tek başına örneklenemeyen, genişletilmek için var olan bir sınıftır. Alanlar, bir yapıcı metot ve eksiksiz yazılmış metotlar barındırabilir; bunların yanında gövdesi olmayan ve her alt sınıfın yazması gereken soyut metotlar da bulunur. Interface ise adlandırılmış bir sözleşmedir: bir türün sağlamayı vaat ettiği metot imzalarının, bazen de özelliklerin listesidir ve kendine ait bir durum tutmaz.
Asıl fark şudur: soyut sınıf, ilişkili türlerin bir işi nasıl yaptığını paylaşır; interface ise bir türün ne yapabildiğini tarif eder. Java, C# ve TypeScript'te bir sınıf yalnızca bir sınıfı genişletebilir ama birçok interface uygulayabilir; bu yüzden soyut sınıf bir türün tek bir ailedeki yerini sabitler, interface'ler ise serbestçe birleştirilebilir: bir Circle hem HasArea hem de Printable olabilir. Soyut sınıflar, temel sınıfın describe() metodunu bir kez yazıp area() metodunu her alt sınıfa bıraktığı template method (şablon metot) desenine uygundur.
İkisi çoğu zaman birlikte çalışır. Yaygın bir tasarım, sözleşmeyi bir interface olarak tanımlar ve onun bir kısmını uygulayan bir soyut sınıfı kullanışlı bir temel olarak ekler; Java'nın List interface'i ve AbstractList sınıfı buna örnektir. Diğer kod yalnızca interface'e bağlı olur; böylece testlerdeki sahte bir uygulama dahil her uygulama verilebilir, ilişkili uygulamalar da kodu soyut sınıf üzerinden paylaşmaya devam eder.
Sık yapılan bir yanlış, Java 8 ve C# 8 interface'lerin varsayılan metot gövdeleri içermesine izin verdiğinde farkın ortadan kalktığı düşüncesidir. Örnek alanları (instance field) ve yapıcı metotlar hâlâ yalnızca sınıflara aittir ve bir sınıf hâlâ yalnızca bir sınıfı genişletebilir. Diller de farklıdır: TypeScript interface'leri derlemeden sonra kaybolur; Python'da ise interface anahtar sözcüğü yoktur, onun yerine abc modülündeki soyut temel sınıflar ya da typing.Protocol kullanılır.
Hangisini kullanmalısınız?
Soyut Sınıf şu durumlarda doğru seçim:
- İlişkili sınıflar yalnızca metot adlarını değil, gerçek kodu ya da alanları paylaşıyor.
- Bir temel sınıfın bir algoritmanın adımlarını sabitlemesini ve bazılarını alt sınıflara bırakmasını istiyorsunuz.
- Alt sınıfların ortak bir yapıcı metoda ya da
protectedyardımcı metotlara ihtiyacı var.
Interface şu durumlarda doğru seçim:
- Birbiriyle ilişkisiz sınıflar, karşılaştırılabilir ya da yazdırılabilir olmak gibi aynı yeteneği sunmalı.
- Bir sınıfın aynı anda birkaç sözleşmeyi yerine getirmesi gerekiyor.
- Uygulamaları değiştirebilmek istiyorsunuz; örneğin testlerde sahte bir uygulama kullanmak için.
- Yalnızca bir nesnenin ya da bir API'nin şeklini tarif etmeniz gerekiyor.
TypeScript'te şekiller: tek bir soyut temel sınıf ya da birkaç interface
// Abstract class: shared code, plus gaps each subclass fills
abstract class Shape {
constructor(public readonly name: string) {}
abstract area(): number; // no body
describe() { return `${this.name}: ${this.area().toFixed(1)}`; }
}
class Circle extends Shape { // extends exactly one class
constructor(private r: number) { super("circle"); }
area() { return Math.PI * this.r ** 2; }
}// Interfaces: contracts only, and a class can take several
interface HasArea { area(): number; }
interface Printable { print(): string; }
class Circle implements HasArea, Printable {
constructor(private r: number) {}
area() { return Math.PI * this.r ** 2; }
print() { return `circle: ${this.area().toFixed(1)}`; }
}
// Any object with the right shape fits, class or not
const square: HasArea = { area: () => 4 };Sık sorulan sorular
Bir sınıf aynı anda hem soyut bir sınıfı genişletip hem de interface uygulayabilir mi?
Evet. Java ya da TypeScript'te class Circle extends Shape implements Printable yazarsınız: bir temel sınıf ve istediğiniz sayıda interface.
Interface'ler varsayılan metotlar içerebiliyorsa neden soyut sınıf kullanılır?
Çünkü interface'ler hâlâ örnek alanları ya da yapıcı metotlar tutamaz. İlişkili sınıflar durum, hazırlık mantığı ya da protected yardımcılar paylaşıyorsa bunların yeri soyut sınıftır.
Python'da interface var mı?
Anahtar sözcük olarak yok. Bu rolü abc modülündeki soyut temel sınıflar üstlenir; typing.Protocol ise tip denetleyicilerinin, TypeScript ve Go'daki gibi şekle göre eşleştirdiği interface'leri tarif eder.