Arayüz yöntemlerinde son argümanlar - amaç nedir?


189

Java'da, finalarabirim yöntemlerinde bağımsız değişkenler tanımlamak ve uygulama sınıfında buna uymamak kesinlikle yasaldır , örneğin:

public interface Foo {
    public void foo(int bar, final int baz);
}

public class FooImpl implements Foo {

    @Override
    public void foo(final int bar, int baz) {
        ...
    }
}

Yukarıdaki örnekte barve VS sınıfında arayüzün bazters finaltanımları vardır.

Aynı şekilde, finalbir sınıf yöntemi diğerini genişlettiğinde abstractveya genişletmediğinde hiçbir kısıtlama uygulanmaz .

finalSınıf yöntemi gövdesi içinde pratik bir değer olsa da , finalarabirim yöntemi parametreleri için herhangi bir nokta belirtmek gerekir mi?


finalkopyalandığından, yerel türlerle hiçbir şey yapmaz.
Paul Tomblin

11
Bir tartışma noktası olarak: Ben sadece denedim ve iki interfacetanım sadece finalbir argümanın niteliğinde değişiyorsa , sonuçta elde edilen .classdosyalar aynı şekilde bayt-bayttır (ve elbette javap -vaynı çıktıyı üretir). Aynı şey, sadece finalbir öznitelikte farklılık gösteren iki sınıf için de geçerlidir !
Joachim Sauer

2
@Paul: referans türleriyle tamamen aynı şeyi yapar: bağımsız değişkenlerin kendisinin değiştirilmesini önler (uygulamada kullanılırsa).
Joachim Sauer

Yöntem imzasında halk kadar önemlidir.
Robin

2
@Deepak: Çok mantıklı gelmediğinde bile her türlü soru üzerinde çalışma örnekleri istediğini görüyorum. Bence bazı soyut düşünceleri öğrenmeyi denemelisiniz: önünüzde yürütülebilir kod olmadan bir sorun hakkında düşünmeyi deneyin . Uzun vadede size çok yardımcı olacaktır.
Joachim Sauer

Yanıtlar:


104

Herhangi bir anlamı yok gibi görünmüyor. Göre Java Dil Özellikleri 4.12.4 :

Değişken bir finalin bildirilmesi, değerinin değişmeyeceği yararlı bir belge işlevi görebilir ve programlama hatalarından kaçınmaya yardımcı olabilir.

Bununla birlikte, bir finalyöntem parametresindeki bir değiştiriciden geçersiz kılınmış yöntemlerin imzalarını eşleştirme kurallarında bahsedilmez ve yalnızca uygulama gövdesi içinde arayan üzerinde bir etkisi yoktur. Ayrıca, Robin tarafından bir yorumda belirtildiği gibi final, bir yöntem parametresindeki değiştiricinin oluşturulan bayt kodu üzerinde hiçbir etkisi yoktur. (Bu, diğer kullanımları için geçerli değildir final.)


Method parametresi de değişken olarak nitelendiriliyor mu? Açıkçası pratikte, ama şartname bağlamında mı?
mindas

11
Gerçek .class dosyasında görünmediğinden, imzaları eşleştirmek için kullanılamaz. Sadece derleyici içindir.
Robin

@mindas - JLS yedi çeşit değişken olduğunu söylüyor . Metod parametreleri listede dördüncü sıradadır.
Ted Hopp

3
Bununla birlikte, finaldeğiştirici uygulayıcı sınıfta uygulanmadığından belgeler işe yaramaz . Arayüz imzanız basitçe yalan söyleyebilir.
Stefan Haberl

Java 8 dil spesifikasyonu artık sekiz çeşit değişken olduğunu söylüyor (yediden - lambda parametreleri eklediler ). Yöntem parametreleri listede dördüncü sıradadır (hayattaki en azından bazı şeyler istikrarlı görünmektedir. :-)).
Ted Hopp

25

Bazı IDE'ler, bir alt sınıfa uygulama yöntemi eklerken soyut / arabirim yönteminin imzasını kopyalar.

Derleyicide herhangi bir fark yarattığına inanmıyorum.

DÜZENLEME: Bunun geçmişte doğru olduğuna inanmamla birlikte, şu anki IDE'lerin artık bunu yaptığını sanmıyorum.


2
Geçerli nokta, bu özellik uygulandığında (veya yanlışlıkla bırakıldığında) birçok IDE olduğunu düşünmeme rağmen :-)
mindas

2
static transientAlanlar kategorisinde olduğunu düşünüyorum . ;)
Peter Lawrey

1
Ve soyut bir sınıfta kamu kurucuları.
Peter Lawrey

1
IntelliJ bunu yapar. Sürümüm IntelliJ IDEA 2016.1.3 Derleme # IU-145.1617.
Dormouse

1
@Dormouse, ilginç, çünkü Android Studio (3.1.4 Build # AI-173.4907809) yapmaz :(
The Godfather

18

Yöntem parametrelerinin son açıklamaları her zaman yalnızca arayan ile asla yöntem uygulamasıyla ilgilidir. Bu nedenle, bunları arayüz yöntemi imzalarında kullanmak için gerçek bir neden yoktur. Tüm yöntem imzalarında son yöntem parametreleri gerektiren aynı tutarlı kodlama standardını izlemek istemiyorsanız. O zaman bunu yapmak güzel.


6

Güncelleme: Aşağıdaki orijinal cevap, soruyu tam olarak anlamadan yazılmıştır ve bu nedenle doğrudan soruyu ele almaz. :)Bununla birlikte, finalanahtar kelimenin genel kullanımını anlamak isteyenler için bilgilendirici olmalıdır .

Soruya gelince, kendi yorumumu aşağıdan alıntılamak istiyorum.

Kendi uygulamanızda nihai olup olmayacağına karar vermek için sizi özgür bırakacak bir argümanın sonunu uygulamak zorunda olmadığınıza inanıyorum .

Ama evet, finalarayüzde ilan edebilmeniz oldukça garip geliyor , ancak uygulamada nihai değil . Aşağıdakilerden biri olursa daha mantıklı olurdu:

a. finalinterface (abstract) yöntemi bağımsız değişkenleri için anahtar kelimeye izin verilmedi (ancak bunu uygulamada kullanabilirsiniz) veya
b. finalarayüzde olduğu gibi bir argüman beyan etmek, onu finaluygulamada beyan edilmeye zorlar (ancak final dışı olanlar için zorlanmaz).


Bir yöntem imzasının finalparametrelere sahip olmasının iki nedenini düşünebilirim : Fasulye ve Nesneler ( Aslında ikisi de aynı nedendir, ancak biraz farklı bağlamlardır. )

Nesneler:

public static void main(String[] args) {
    StringBuilder cookingPot = new StringBuilder("Water ");
    addVegetables(cookingPot);
    addChicken(cookingPot);
    System.out.println(cookingPot.toString());
    // ^--- OUTPUT IS: Water Carrot Broccoli Chicken ChickenBroth 
    //      We forgot to add cauliflower. It went into the wrong pot.
}

private static void addVegetables(StringBuilder cookingPot) {
    cookingPot.append("Carrot ");
    cookingPot.append("Broccoli ");
    cookingPot = new StringBuilder(cookingPot.toString());
    //   ^--- Assignment allowed...
    cookingPot.append("Cauliflower ");
}

private static void addChicken(final StringBuilder cookingPot) {
    cookingPot.append("Chicken ");
    //cookingPot = new StringBuilder(cookingPot.toString());
    //     ^---- COMPILATION ERROR! It is final.
    cookingPot.append("ChickenBroth ");
}

finalAnahtar kelime kazara yeni yaratmayacağı sağlanmalıdır yerel bunu yapmaya çalışırken bir derleme hatası göstererek tencereyi. Bu, tavuk suyunun, addChickenyöntemin sahip olduğu orijinal tenceremize eklenmesini sağladı . Bunu addVegetableskarnabaharı kaybettiğimiz yerle karşılaştırın, çünkü bunu orijinal tencerenin yerine yeni bir yerel tencereye ekledi .

Fasulye: Nesnelerle aynı kavramdır (yukarıda gösterildiği gibi) . Fasulye esas Objectolarak Java'dadır. Bununla birlikte, fasulye (JavaBeans), çeşitli uygulamalarda, tanımlanmış bir ilgili veri koleksiyonunu depolamak ve dolaşmak için uygun bir yol olarak kullanılır. Nasıl addVegetablesyeni bir pişirme kabı oluşturarak StringBuilderve karnabahar ile fırlatarak pişirme işlemini bozabilir gibi, JavaBean bir pişirme kabı ile de aynısını yapabilir .


Tamam. Bu soruya gerçekten doğru bir cevap değil (çünkü arayüz yöntemini uygulamamın, arayüz böyle söylese bile son argümanları almak zorunda olmadığım için), ancak bunun nedeninin iyi bir açıklaması yöntem parametrelerini nihai yapmak iyi bir fikirdir.
Phil

Kendi uygulamanızda nihai olup olmayacağına karar vermek için sizi özgür bırakacak bir argümanın sonunu uygulamak zorunda olmadığınıza inanıyorum . Ama evet, finalarayüzde ilan edebilmeniz oldukça garip geliyor , ancak uygulamada nihai değil . (A) final arabirimi (soyut) yöntem bağımsız değişkenleri için (a) anahtar sözcüğüne izin verilmiyorsa (ancak bunu uygulamada kullanabilirsiniz) veya (b)final arabirimdeki gibi bir bağımsız değişken bildirmek, bunu finaluygulamada bildirilmeye zorlarsa daha anlamlı olurdu (ancak final dışı olanlar için zorunlu değildir).
ADTC

"Bu soruya gerçekten doğru bir cevap değil" Haklısın, ne düşündüğümü bilmiyorum ... Temmuz ayının erken saatleri falan olmalıydı. :)
ADTC

2

Nihai olsun ya da olmasın bir uygulama detayı olduğu için bunun gereksiz bir ayrıntı olabileceğine inanıyorum.

(Bir arabirimdeki benzer bildirme yöntemlerini / üyelerini genel olarak sıralayın.)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.