Ne zaman bir PHP kullanmalıyım interface
ve ne zaman bir abstract class
?
Nasıl değiştirebilirim abstract class
bir karşı in interface
?
Ne zaman bir PHP kullanmalıyım interface
ve ne zaman bir abstract class
?
Nasıl değiştirebilirim abstract class
bir karşı in interface
?
Yanıtlar:
Sisteminizde çalışan geliştiricileri (siz de dahil), oluşturacakları sınıflara belirli sayıda yöntem uygulamaya zorlamak istediğinizde bir arabirim kullanın.
Sisteminizde çalışan geliştiricileri (siz de dahil) belirli sayıda yöntemi uygulamaya zorlamak istediğinizde soyut bir sınıf kullanın ve onlara çocuklarının sınıflarını geliştirmelerine yardımcı olacak bazı temel yöntemler sunmak istiyoruz.
Akılda tutulması gereken başka bir şey, istemci sınıflarının yalnızca bir soyut sınıfı genişletebileceği, oysa birden fazla arabirim uygulayabileceğidir. Dolayısıyla, davranış sözleşmelerinizi soyut sınıflarda tanımlıyorsanız, bu her çocuk sınıfının yalnızca tek bir sözleşmeye uygun olabileceği anlamına gelir. Bazen, kullanıcı programcılarınızı belirli bir yol boyunca zorlamak istediğinizde bu iyi bir şeydir. Diğer zamanlarda kötü olurdu. PHP'nin Sayılabilir ve Yineleyici arabirimlerinin arabirimler yerine soyut sınıflar olup olmadığını düşünün.
Hangi yoldan gideceğinizden emin değilseniz yaygın olan bir yaklaşım ( aşağıda cletus tarafından belirtildiği gibi ) bir arayüz oluşturmak ve daha sonra soyut sınıfınızın bu arayüzü uygulamasını sağlamaktır.
An Abstract Class
ve an arasındaki farklar Interface
:
Soyut Sınıflar
Soyut bir sınıf bazı işlevler sağlayabilir ve geri kalanını türetilmiş sınıf için bırakabilir .
Türetilmiş sınıf , temel sınıfta tanımlanan somut fonksiyonları geçersiz kılabilir veya geçersiz kılabilir .
Soyut bir sınıftan genişletilmiş bir çocuk sınıfı mantıksal olarak ilişkili olmalıdır.
Arayüz
Bir arabirim herhangi bir işlev içeremez . O sadece yöntemlerin tanımlarını içerir.
Türetilmiş sınıf , arabirimde tanımlanan tüm yöntemler için kod SAĞLAMALIDIR .
Tamamen farklı ve ilişkili olmayan sınıflar bir arabirim kullanılarak mantıksal olarak birlikte gruplandırılabilir.
abstract class X implements Y
ve class X implements Y
?
abstract class X implements Y
X'in toplu işlevselliğinin türetilmiş bir sınıfta uygulanması gerektiğini ve hem soyut hem de türetilmiş sınıfın Y'de tanımlanan işlevleri içermesi gerektiğini belirtirken, class X implements Y
yalnızca X sınıfının Y'de tanımlanan işlevleri içermesi gerektiğini belirtirsiniz. XI, aslında Y'nin bir arabirim olarak tanımlanmasını atlamayacak ve yalnızca Y'deki işlevleri türetici sınıfta uygulandıklarından emin olmak için genel / korumalı / özel soyut işlev olarak uygulayacağından başka bir sınıf tarafından uygulanması amaçlanmamıştır.
Soyut sınıflar neden kullanılmalı? Aşağıdaki basit bir örnektir. Diyelim ki şu kodumuz var:
<?php
class Fruit {
private $color;
public function eat() {
// chew
}
public function setColor($c) {
$this->color = $c;
}
}
class Apple extends Fruit {
public function eat() {
// chew until core
}
}
class Orange extends Fruit {
public function eat() {
// peeling
// chew
}
}
Şimdi sana bir elma veriyorum ve sen yiyorsun. Tadı nasıl? Elma gibi tadı var.
<?php
$apple = new Apple();
$apple->eat();
// Now I give you a fruit.
$fruit = new Fruit();
$fruit->eat();
Bu tat neye benziyor? Pek mantıklı değil, bu yüzden bunu yapamamanız gerekir. Bu, Fruit sınıfını ve içindeki eat yöntemini soyut yaparak başarılır.
<?php
abstract class Fruit {
private $color;
abstract public function eat(){}
public function setColor($c) {
$this->color = $c;
}
}
?>
Soyut bir sınıf bir arayüz gibidir, ancak bir soyut sınıfta yöntemleri tanımlayabilirken, bir arayüzde hepsi soyuttur. Soyut sınıflar hem boş hem de çalışma / somut yöntemlere sahip olabilir. Arayüzlerde, burada tanımlanan fonksiyonların bir gövdesi olamaz. Soyut sınıflarda, yapabilirler.
Gerçek bir dünya örneği:
<?php
abstract class person {
public $LastName;
public $FirstName;
public $BirthDate;
abstract protected function write_info();
}
final class employee extends person{
public $EmployeeNumber;
public $DateHired;
public function write_info(){
//sql codes here
echo "Writing ". $this->LastName . "'s info to emloyee dbase table <br>";
}
}
final class student extends person{
public $StudentNumber;
public $CourseName;
public function write_info(){
//sql codes here
echo "Writing ". $this->LastName . "'s info to student dbase table <br>";
}
}
///----------
$personA = new employee;
$personB = new student;
$personA->FirstName="Joe";
$personA->LastName="Sbody";
$personB->FirstName="Ben";
$personB->LastName="Dover";
$personA->write_info();
// Writing Sbody's info to emloyee dbase table
$personB->write_info();
// Writing Dover's info to student dbase table
What does that taste like? Well, it doesn't make much sense, so you shouldn't be able to do that.
Artık soyut biliyorum!
final
anahtar kelimeye? Harika gönderi, teşekkürler.
En iyi uygulama, sözleşmeyi ve soyut bir sınıfı belirtmek için bir arayüz kullanmaktır. Bu soyut sınıf, çok sayıda kazan plakasını doldurabilir, böylece sadece belirli bir uygulamayı kullanmaya zorlamadan ihtiyacınız olan veya istediğiniz şeyi geçersiz kılarak bir uygulama oluşturabilirsiniz.
Sadece bunu karışıma atmak için, ancak Cletus'un soyut bir sınıfla birlikte bir arayüz kullanarak bahsettiği gibi, genellikle tasarım düşünümü netleştirmek için arayüzü kullanırım.
Örneğin:
<?php
class parser implements parserDecoratorPattern {
//...
}
Bu şekilde, kodumu okuyan (ve bir Dekoratör Deseninin ne olduğunu bilen) hemen bilecek olan a) ayrıştırıcımı nasıl oluşturduğumu ve b) dekoratör desenini uygulamak için hangi yöntemlerin kullanıldığını görebilecektir.
Ayrıca, burada bir Java / C ++ / etc programcısı olmamak için temelden uzak olabilirim, ancak veri türleri burada devreye girebilir. Nesneleriniz bir türdendir ve nesnelerin etrafından geçirdiğinizde programlı olarak önemlidir. Anlaşılabilir öğelerinizi arayüze taşımak, yalnızca yöntemlerin döndürdüğü türleri belirler, ancak onu uygulayan sınıfın temel türünü değil.
Geç oldu ve daha iyi bir psudo-code örneği düşünemiyorum, ama işte gidiyor:
<?php
interface TelevisionControls {};
class Remote implements TelevisionControls {};
class Spouse implements TelevisionControls {};
Spouse spouse = new Spouse();
Remote remote = new Remote();
isSameType = (bool)(remote == spouse)
Temel fark, soyut bir sınıfın varsayılan uygulamayı içerebileceği, ancak arabirimin yapamayacağıdır.
Arayüz, herhangi bir uygulama olmadan davranış sözleşmesidir.
Ayrıca, sadece diğer herhangi bir OO dilinin bir tür arayüzlere ve soyutlamaya da sahip olması, PHP'dekiyle aynı anlama ve amaca sahip oldukları anlamına gelmediğini buraya eklemek isterim. Soyutlama / arayüzlerin kullanımı biraz farklıdır, ancak PHP'deki arayüzlerin gerçek bir işlevi yoktur. Sadece semantik ve şema ile ilgili nedenlerle kullanılırlar. Mesele, geliştiricinin tamamen farklı bir kullanım planına sahip olup olmadığına bakılmaksızın, gelecekteki uzantılar için mümkün olduğunca esnek, genişletilebilir ve güvenli bir projeye sahip olmaktır.
İngilizceniz yerli değilse, Soyutlama ve Arayüzlerin gerçekte ne olduğunu araştırabilirsiniz. Ve eşanlamlıları da arayın.
Ve bu bir metafor olarak size yardımcı olabilir:
ARAYÜZ
Diyelim ki, çilek ile yeni bir çeşit kek pişiriyorsunuz ve malzemeleri ve adımları açıklayan bir tarif hazırladınız. Neden sadece bu kadar lezzetli olduğunu ve misafirlerinizin bunu sevdiğini biliyorsunuz. Sonra diğer insanların da bu pastayı deneyebilmesi için tarifinizi yayınlamaya karar verdiniz.
Buradaki nokta
- doğru yapmak
- dikkatli olmak
- kötü gidebilecek şeyleri önlemek için (çok fazla çilek ya da bir şey gibi)
- deneyen insanlar için kolay tutmak
- ne yapacağınızı (karıştırmak gibi) söylemek )
- hangi şeyleri yapabileceğinizi söylemek zorundasınız
Tam olarak BU, arayüzleri tanımlayan şeydir. Bu bir rehber, tarifin içeriğini gözlemleyen bir dizi talimattır. PHP'de bir proje yaratırsınız ve GitHub'da veya arkadaşlarınızla ya da her neyse kodu sağlamak istersiniz. Bir arayüz insanların yapabilecekleri ve yapmamanız gereken şeydir. Onu tutan kurallar - birine uymazsanız, tüm yapı kırılacaktır.
SOYUTLAMA
Bu metaforla devam etmek için ... hayal edin, bu sefer o pastayı yiyen misafirsiniz. O zaman şimdi tarifi kullanarak o pastayı deniyorsun. Ancak yeni malzemeler eklemek veya tarifte açıklanan adımları değiştirmek / atlamak istiyorsunuz. Peki sırada ne var? O pastanın farklı bir versiyonunu planlayın. Bu kez siyah meyveler ve saman meyveleri ve daha vanilyalı krema ile ... nefis.
Orijinal pastanın bir uzantısı olarak düşünebilirsiniz. Temelde yeni bir tarif oluşturarak bir soyutlama yapıyorsunuz çünkü bu çok farklı. Birkaç yeni adımı ve diğer malzemeleri var. Bununla birlikte, siyah dut versiyonunun orijinalinden aldığınız bazı parçaları vardır - bunlar o pastanın her türünün sahip olması gereken temel adımlardır. Tıpkı süt gibi malzemeler gibi - Her türetilmiş sınıfın sahip olduğu budur.
Şimdi malzemeleri ve adımları değiştirmek istiyorsunuz ve bunlar o pastanın yeni versiyonunda tanımlanmalı ZORUNLU. Bunlar yeni kek için tanımlanması gereken soyut yöntemlerdir , çünkü kekin içinde bir meyve olmalı ama hangisi? Yani bu sefer siyah meyveleri alıyorsunuz. Bitti.
İşte, pastayı uzattınız, arayüzü takip ettiniz ve ondan soyutlanmış adımlar ve malzemeler aldınız.
Zaten mükemmel cevapların bazılarına eklemek için:
Soyut sınıflar bir derece uygulama sağlar, arayüzler saf şablonlardır. Bir arayüz sadece işlevselliği tanımlayabilir , asla uygulayamaz.
Arabirimi uygulayan her sınıf, tanımladığı tüm yöntemleri uygulamayı taahhüt eder veya özet olarak bildirilmelidir.
Arayüzler, Java gibi PHP'nin birden fazla mirası desteklemediğini yönetmeye yardımcı olabilir. Bir PHP sınıfı yalnızca tek bir üst öğeyi genişletebilir. Ancak, istediğiniz kadar çok arabirimi uygulamak için bir sınıf sözü verebilirsiniz.
type: uyguladığı her arabirim için sınıf ilgili türü alır. Herhangi bir sınıf bir arabirim (veya daha fazla arabirim) uygulayabileceğinden, arabirimler başka türlü ilgisiz türlere etkin bir şekilde katılır.
bir sınıf hem bir üst sınıfı genişletebilir hem de istediğiniz sayıda arabirimi uygulayabilir:
class SubClass extends ParentClass implements Interface1, Interface2 {
// ...
}
Lütfen ne zaman bir arayüz kullanmalıyım ve ne zaman soyut sınıf kullanmalıyım?
Yalnızca hiç uygulama içermeyen bir şablon sağlamanız gerektiğinde bir arabirim kullanın ve bu arabirimi uygulayan herhangi bir sınıfın onu uygulayan diğer sınıflarla aynı yöntemlere sahip olduğundan emin olmak istediğinizde (en azından).
Diğer nesneler (kısmen oluşturulmuş bir sınıf) için temel oluşturmak istediğinizde soyut bir sınıf kullanın. Soyut sınıfınızı genişleten sınıf, tanımlanan / uygulanan bazı özellikleri veya yöntemleri kullanır:
<?php
// interface
class X implements Y { } // this is saying that "X" agrees to speak language "Y" with your code.
// abstract class
class X extends Y { } // this is saying that "X" is going to complete the partial class "Y".
?>
Soyut sınıfımı bir arayüze nasıl değiştirebilirim?
İşte basitleştirilmiş bir örnek / örnek. Uygulama ayrıntılarını çıkarın. Örneğin, soyut sınıfınızı şununla değiştirin:
abstract class ClassToBuildUpon {
public function doSomething() {
echo 'Did something.';
}
}
için:
interface ClassToBuildUpon {
public function doSomething();
}
Felsefi açıdan:
Soyut bir sınıf bir "eşittir" ilişkisini temsil eder. Diyelim ki meyvelerim var, ortak sorumlulukları ve ortak davranışları paylaşan bir meyve soyut sınıfım olacaktı.
Bir arayüz "yapmalı" ilişkisini temsil eder. Bence bir arayüz (bir junior dev'in görüşüdür), bir eylem veya bir eyleme yakın bir şeyle adlandırılmalıdır, (Üzgünüm, kelimeyi bulamıyorum, İngilizce ana dili konuşanı değilim) IEatable diyelim. Yenilebileceğini biliyorsunuz, ama ne yediğinizi bilmiyorsunuz.
Kodlama açısından:
Nesnelerinizde çoğaltılmış kod varsa, ortak davranışa sahip olduklarının bir göstergesidir, yani kodu yeniden kullanmak için bir arabirimle yapamayacağınız soyut bir sınıfa ihtiyacınız olabilir.
Bir başka fark, bir nesnenin ihtiyacınız olduğu kadar çok arabirim uygulayabilmesidir, ancak "elmas sorunu" nedeniyle yalnızca bir soyut sınıfa sahip olabilirsiniz (nedenini öğrenmek için buraya göz atın! Http://en.wikipedia.org/wiki/ Çoklu_geliş # The_diamond_problem )
Muhtemelen bazı noktaları unutuyorum ama umarım bazı şeyleri açıklığa kavuşturabilir.
Not: "bir" / "yapmalı" Vivek Vermani'nin cevabı tarafından getirildi, cevabını çalmak istemedim, sadece terimleri tekrar kullanmak için onları sevdim çünkü!
Soyut bir sınıf ve bir arayüz arasındaki teknik farklar, diğer cevaplarda tam olarak listelenmiştir. Nesne yönelimli programlama uğruna kod yazarken bir sınıf ve bir arayüz arasında seçim yapmak için bir açıklama eklemek istiyorum.
Bir sınıf bir varlığı temsil ederken, bir arayüz davranışı temsil etmelidir.
Bir örnek verelim. Bilgisayar monitörü bir varlıktır ve bir sınıf olarak temsil edilmelidir.
class Monitor{
private int monitorNo;
}
Size bir ekran arayüzü sağlamak için tasarlanmıştır, bu nedenle işlevsellik bir arayüz tarafından tanımlanmalıdır.
interface Display{
void display();
}
Diğer cevaplarda açıklandığı gibi düşünülmesi gereken birçok şey var, ancak bu kodlama sırasında çoğu insanın görmezden geldiği en temel şey.
PHP
Her ikisini de ne zaman kullanmanız gerektiğine dair bir örnek eklemek istedim. Şu anda genel amaçlı ERP çözümünde bir veritabanı modeline bağlı bir dosya işleyicisi yazıyorum.
Bu şekilde, farklı dosyalar için birden fazla şablon ve net bir ayrım ile ortak bir arayüz yöntemleri setine sahip olurum. Arayüz, temel bir soyut sınıfla olanlardan ziyade erişim yöntemlerine doğru benzetme sağlar.
Dahası, farklı dosya depolama hizmetleri için adaptörler yapacağım zaman, bu uygulama, arayüzün tamamen farklı bağlamlarda başka bir yerde kullanılmasına izin verecektir.
abstract
veinterface
sınıflarını anlamaya çalışıyordum , yazınız her şeyi açıklığa kavuşturdu. Çok teşekkürler Alan