2011-09-19 32 views
5

Tamam. Çocuk sınıflarının herhangi biri için bir üst sınıfta ayarlanmış sabitleri miras almaya çalışıyorum.Inlineiting Sabit satır içi satır içi paketleri

#!/usr/bin/perl 
use strict; 
use warnings; 

package Car; 
use Exporter qw(import); 
our @EXPORT_OK = ('WHEELS', 'WINGS'); 

use constant WHEELS => 4; 
use constant WINGS => 0; 

sub new { 
    my ($class, %args) = @_; 
    my $self = { 
     doors => $args{doors}, 
     colour => $args{colour}, 
     wheels => WHEELS, 
     wings => WINGS, 
    }; 
    bless $self, $class; 
    return $self; 
} 

package Car::Sports; 
use base qw(Car); 

sub new { 
    my ($class, %args) = @_; 
    my $self = { 
     doors => $args{doors}, 
     engine => $args{engine}, 
     wheels => WHEELS, 
     wings => WINGS, 
    }; 
    bless $self, $class; 
    return $self; 
} 

package main; 
my $obj = Car->new(doors => 4, colour => "red"); 
print Dumper $obj; 

my $obj2 = Car::Sports->new(doors => 5, engine => "V8"); 

print Dumper $obj2; 
__END__ 

hatadır:

Bareword "WHEELS" not allowed while "strict subs" in use at ./t.pl line 30. 
Bareword "WINGS" not allowed while "strict subs" in use at ./t.pl line 30. 
Execution of ./t.pl aborted due to compilation errors. 

Şimdi, biraz araştırma yapmadan göndermek için buraya gelmedik. Bir seçeneğin, Car::Sports numaralı telefondan use Car qw(WHEELS WINGS) olduğunu anlıyorum. Ben sınıfları aynı dosyadaki tüm satır içi oldukları için, aşağıdaki hatayı alıyorum bunu yaparsan Ancak:

Can't locate Car.pm in @INC 

çeşitli nedenlerle için, ben bir dosyada Paketlerimde tutmak gerekir. Bunun etrafında bir yolu var mı? Sabitler temel olarak sadece subs, normal bir yöntem için aynı doğru olmazken neden onları almak zorundayım?

Son olarak, ben de bunu yapabilirim biliyorum:

package Car::Sports; 
use base qw(Car); 

sub new { 
    my ($class, %args) = @_; 
    my $self = { 
     doors => $args{doors}, 
     engine => $args{engine}, 
     wheels => Car::WHEELS, 
     wings => Car::WINGS, 
    }; 
    bless $self, $class; 
    return $self; 
} 

Ve gayet ... Ama sınıfların bir dizi var ve ebeveyn isim zorunda olduğunu sabitlerin miras daha genel yapmak istiyorum sınıf açıkça (ve bazen sadece ana sınıf değil, büyükbaba).

Herhangi bir işaretçi için şimdiden çok teşekkürler!

Alkış

cevap

6

Bir geçici çözüm

 
package Car::Sports; 
use base qw(Car); 
Car->import(qw(WHEELS WINGS)); 

VECar::Sports yapıcı içinde Sigils kullanmak satırını dahil etmektir:

... 
wheels => &WHEELS, 
wings => &WINGS, 
... 

Sizin Car sınıf onun @EXPORTS_OK tanımlayan değil çalışma zamanına kadar liste. Car::Sports yapıcısının derleme zamanında ayrıştırılmasından ve derleyicininve WINGS ad alanı içinde ad alanı içinde olması gerektiğini bildiğinden, imzalayanlar gereklidir. Ayrıca kendi içinde Car sınıfı belirlenerek bu entrikaları önlemek olabilir

package Car; 
our @EXPORT_OK; 
BEGIN {@EXPORT_OK = qw(WHEELS WINGS)} # set at compile not run time 
... 

package Car::Sports; 
use base qw(Car); 
BEGIN {Car->import('WHEELS','WINGS')} # import before c'tor is parsed 

:


Sigils önlemenin tek yolu derleme sırasında Car 'ın ihracatını tanımlamaktır Car.pm dosya. Sonra sadece otomatik olarak çalışır alacağı

use Car qw(WHEELS WINGS); 

ve derleme zamanında çözümlenen Car.pm dosyada herşeyi VE (Car::import bir çağrı tarafından tetiklenen) Exporter::import yöntemi söylemek ve geçerli ad alanına istediğiniz sembolleri içe olurdu .

+0

Mükemmel! Bunu gerçekten iyi açıkladın ve bana bir şey öğrettin! – wawawawa

+0

Ayrıca, "Araba :: Spor", "Araba" alt sınıfının "Araba" Sports "Araba" yöntemlerine * erişmesini, ancak * işlevlerinin "& WHEELS" ve "& WINGS" gibi değil * yapmasını sağlar. 'Araba' sınıfına bazı yöntemler ekleyene kadar 'temel qw (Araba)' işlevini kullanmak gereksizdir. – mob

3

Bu değişiklik sizin ihtiyaçlarınıza uygun olabilir mi?VERİLERİ :: Damper kullanma

[...] 
    wheels => $class->SUPER::WHEELS, 
    wings => $class->SUPER::WINGS, 
    [...] 

elde edersiniz:

$VAR1 = bless({ 
      'wings' => 0, 
      'colour' => 'red', 
      'doors' => 4, 
      'wheels' => 4 
      }, 'Car'); 
$VAR1 = bless({ 
      'wings' => 0, 
      'engine' => 'V8', 
      'doors' => 5, 
      'wheels' => 4 
      }, 'Car::Sports'); 
+0

Harika ... Bunun için teşekkürler. SUPER ile oynamaktaydım, ama '$ class' kullanmamıştım. – wawawawa

3

Alternatif, sen use ne yaptığını tam olarak yapabileceği:

BEGIN { 
    package Car; 
    use Exporter qw(import); 
    @EXPORT_OK = qw(WHEELS); 

    ... 

    $INC{'Car.pm'} = 1; 
} 

BEGIN { 
    package Car::Sports; 

    use Car qw(WHEELS); 
    @ISA = 'Car'; 

    ... 

    $INC{'Car/Sports.pm'} = 1; 
} 
+0

ikegami - Sanırım seni Perlmonks'tan hatırlıyorum! Yorumları takdir ediyorum, teşekkür ederim! – wawawawa

0

Genellikle şey herhangi pakete sabit olduğunu açığa Bunu tanımlayandan başka bir şey aslında kötü bir fikirdir. Bu, diğer şeylerin yanı sıra, kodunuzun diğer alanlarında sabit olan değerlere başvururken alışılmadık biçimleri kullanmaya karşı olduğunu ileri sürmektedir.

constant modül aslında sadece iyi çalışır biz mademki sınıf yöntemleri gibi sabitleri çağırarak gibi sabitler bahsediyoruz gerçeğini gizleyen bir çağırma formu destekler: tek aslında sabitlerini devralır nasıl

package Car; 
use constant default_wheel_count => 4; 

package Car::Sports; 

sub new { 
    my ($class) = @_; 

    return bless { 
     wheels => $class->default_wheel_count, 
    } => $class; 
} 

That ama yine de yanlış bir yaklaşım. Copypasta'ları yalnızca bu niteliklerin oluşturulmasını uygulayan sınıflardan gelen sabitleri kullanarak ortadan kaldırmak, yapılacak en doğru şeydir.