Türetilmiş sınıfı süper yöntemi çağırmaya nasıl zorlayabilirim? (Android'in yaptığı gibi)


85

Yeni oluştururken merak ediyordum Activitysınıfları ve daha sonra ağır basan onCreate()hep oto eklense Tutulma, yöntem: super.onCreate(). Bu nasıl olur? Soyut veya üst sınıfta bunu zorlayan bir java anahtar kelimesi var mı?

Süper sınıfı aramamanın yasa dışı olup olmadığını bilmiyorum, ancak bazı yöntemlerde bunu yapmadığım için bir istisna atıldığını hatırlıyorum. Bu aynı zamanda java'da yerleşik mi? Bunu yapmak için bir anahtar kelime kullanabilir misin? Veya nasıl yapılır?


Ben de bunu bilmek istiyorum. Süper.onCreate () çağrısını kaldırırsam, sadece Eclipse yardımcı olmakla kalmıyor, uygulama "super.onCreate () 'i çağırmadım" diyen bir çalışma zamanı hatası veriyor. Yani evet, bu gerçekten sizi süper yöntemi aramaya zorluyor. Ama nasıl?
Rodrigo Castro

@RodrigoCastro Her yöntem için javadocs gözden geçirebilirsiniz. Örneğin onCreate () .

Yanıtlar:


10

İşte kaynağı Activity#onCreate()- neredeyse tüm yorumlar ( orijinal - bkz. Satır ~ 800 ):

/**
 * Called when the activity is starting.  This is where most initialization
 * should go: calling {@link #setContentView(int)} to inflate the
 * activity's UI, using {@link #findViewById} to programmatically interact
 * with widgets in the UI, calling
 * {@link #managedQuery(android.net.Uri , String[], String, String[], String)} to retrieve
 * cursors for data being displayed, etc.
 *
 * <p>You can call {@link #finish} from within this function, in
 * which case onDestroy() will be immediately called without any of the rest
 * of the activity lifecycle ({@link #onStart}, {@link #onResume},
 * {@link #onPause}, etc) executing.
 *
 * <p><em>Derived classes must call through to the super class's
 * implementation of this method.  If they do not, an exception will be
 * thrown.</em></p>
 *
 * @param savedInstanceState If the activity is being re-initialized after
 *     previously being shut down then this Bundle contains the data it most
 *     recently supplied in {@link #onSaveInstanceState}.  <b><i>Note: Otherwise it is null.</i></b>
 *
 * @see #onStart
 * @see #onSaveInstanceState
 * @see #onRestoreInstanceState
 * @see #onPostCreate
 */
protected void onCreate(Bundle savedInstanceState) {
    mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
            com.android.internal.R.styleable.Window_windowNoDisplay, false);
    mCalled = true;
}

bu yüzden, benim tahminim, ADT Eclipse eklentisinin bu çağrıyı super.onCreate()sizin için otomatik olarak eklediği olacaktır . Yine de toplam bir tahmin.


2
Sanırım mCalled = trueolası bir istisna için de kullanılıyor. Belki de değil, onCreate()ama gerçekten böyle bir istisna atıldığında, bu basit kalıbı kullanacaktır.
Peterdk

194

Bu, destek ek açıklama kitaplığına eklenir:

dependencies {
    compile 'com.android.support:support-annotations:22.2.0'
}

http://tools.android.com/tech-docs/support-annotations

@Kafadergisi


Evet, burada kafasına çivi çaktın. Teşekkürler.
SMBiggs

Henüz denenmedi, ancak belgeleri okuyun. Bu harika olacak sanırım. Kabul edilen cevap bu olmalıdır.
Rizwan Sohaib

1
Bunun dışında tüm diğer cevaplar tamamen saçmalık. Kabul edilmelidir.
Le_Enot

3
@RizwanSohaib sizi bir şey yapmaya zorlamaz. Onu aramanız gerektiğini vurgular ve size bildirir. Daha karmaşık bir şey yapmak için, bir açıklama işlemcisine veya mantığı kendiniz uygulamanız gerekecek. IDE'ye bağlı olarak, sizin de inşa etmenizi engellemelidir.
frostymarvelous

1
Mükemmel cevap. Çok teşekkürler
Võ Quang Hòa

82

Alt sınıfları üst sınıfın mantığını yürütmeye zorlamak istiyorsanız , ortak bir model aşağıdaki gibidir:

public abstract class SuperClass implements SomeInterface
{
    // This is the implementation of the interface method
    // Note it's final so it can't be overridden
    public final Object onCreate()
    {
        // Hence any logic right here always gets run
        // INSERT LOGIC

        return doOnCreate();

        // If you wanted you could instead create a reference to the
        // object returned from the subclass, and then do some
        // post-processing logic here
    }

    protected abstract Object doOnCreate();
}

public class Concrete extends SuperClass
{
    @Override
    protected Object doOnCreate()
    {
        // Here's where the concrete class gets to actually do
        // its onCreate() logic, but it can't stop the parent
        // class' bit from running first

        return "Hi";
    }
}

Bu aslında Eclipse'i uygulamaya otomatik olarak bir üst sınıf çağrısı eklemeye yönlendiren şey hakkındaki sorunuza cevap vermez; ama o zaman bunun her zaman silinebileceği için yine de gitmenin yolu olduğunu düşünmüyorum.

Bir yöntemin süper sınıfın sürümünü bir Java anahtar sözcüğü veya buna benzer bir şeyle çağırması gerektiğini gerçekten zorlayamazsınız. İstisnalarınızın, beklenen değişmezleri kontrol eden ebeveyn sınıfındaki bir koddan veya yaklaşımınız tarafından geçersiz kılınan bir şeyden geldiğinden şüpheleniyorum. Çağrı yapamadığınız için bunun bir istisna atmaktan biraz farklı olduğunu unutmayın super.onCreate().


8

Üst sınıf yönteminin de çağrıldığından kesinlikle emin olmak istiyorsanız, biraz kandırmanız gerekir: Üst sınıf yönteminin üzerine yazılmasına izin vermeyin, ancak geçersiz kılınabilen bir korumalı yöntemi çağırmasını sağlayın.

class Super
{
   public final void foo() {
      foo_stuff();
      impl_stuff();
   }

   protected void impl_stuff() {
      some_stuff_that_you_can_override();
   }
}

class Base extends Super
{
  protected void impl_stuff() { 
     my_own_idea_of_impl();
  }
}

Bu şekilde, kullanıcının Super.foo () veya Base.foo () 'yu çağırması gerekir ve bu her zaman nihai olarak ilan edildiği gibi temel sınıf sürüm olacaktır. Uygulamaya özgü şeyler impl_stuff () içindedir ve geçersiz kılınabilir.


8

Asıl sorunuza cevap vermek için, super.onCreate () çağrısının otomatik olarak oluşturulması ADT eklentisinin bir özelliğidir. Java'da, bir alt sınıfı, bir yöntemin süper uygulamasını (afaik) çağırmaya doğrudan zorlayamazsınız (geçici çözüm için diğer yanıtlarda açıklanan modele bakın). Ancak, Android'de Activity nesnelerini (veya Hizmet nesnelerini) doğrudan örneklemediğinizi unutmayın - sisteme bir Niyet iletirsiniz ve sistem nesneyi başlatır ve onCreate () öğesini çağırır (diğer yaşam döngüsü yöntemleriyle birlikte). Bu nedenle, sistemin Activity örneğine doğrudan bir nesne referansı vardır ve onCreate () 'in üst sınıf uygulamasında true olarak ayarlanmış bazı Boolean'ları kontrol edebilir (muhtemelen). Tam olarak nasıl uygulandığını bilmesem de, muhtemelen şuna benziyor:

class Activity
{
  onCreate()
  {
    superCalled = true;
    ...
  }
  ...
}

Ve Intent'i alan ve ondan Activity nesnesini başlatan "sistem" seviyesi sınıfında:

...
SomeActivitySubclass someActivitySubclassObject = new SomeActivitySubclass();
someActivitySubclassObject.onCreate();
if (!someActivityObject.isSuperCalled())
{
  Exception e = new Exception(...) //create an exception with appropriate details
  throw e;
}

Tahminim muhtemelen bundan biraz daha karmaşık, ama siz anladınız. Eclipse, ADT eklentisi kolaylık olması açısından çağrıyı otomatik olarak oluşturur. Mutlu kodlamalar!


4

Java'da süper çağrıyı zorlayan hiçbir şey yoktur ve istemeyeceğiniz birçok örnek vardır. Süper çağrıyı zorlayabileceğiniz tek yer kuruculardadır. Tüm kurucuların bir üst sınıf kurucusu çağırması gerekir. Açıkça bir tane yazmazsanız bir (argümansız yapıcı) eklenir ve argümansız yapıcı yoksa, onu açıkça çağırmanız gerekir.


3

Eclipse sadece yardımcı oluyor ve size, isterseniz üst sınıf uygulamasını çağırabileceğinizi hatırlatıyor.

Muhtemelen bir hata alıyorsunuz çünkü onun uygulamasını çağırmıyorsunuz çünkü üst sınıfın yaptığı gerekli bir şeyi yapmıyorsunuz.


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.