2016-06-07 22 views
20

Bir kurucuda bir InputStream açarken ve sonra bir süper kurucuya geçirirken kaynakları kullanmaya çalışmak için iyi bir yol var mı? super yapıcı ilk deyimi olması gerektiğinden elbette bu izin verilmezSüper kurucuyu çağırırken kaynaklar ile çalışın

public class A { 
    public A(InputStream stream) { 
     // Do something with the stream but don't close it since we didn't open it 
    } 
} 

public class B { 
    public B(File file) { 
     // We open the stream so we need to ensure it's properly closed 
     try (FileInputStream stream = new FileInputStream(file)) { 
      super(new FileInputStream(file)); 
     } 
    } 
} 

Ama:

Temelde ne yapmak istediğinizi budur. Bunu başarmanın iyi bir yolu var mı?

+2

Arayanın giriş akışını 'public B (InputStream in)' konumuna getirmesini ve kapatmasını istiyorum. Türetilmiş sınıfı, temel sınıftan daha az yönlü hale getirmek için bir sebep yok. – EJP

+0

Daha çok yönlü, aynı zamanda daha kullanışsız. Her ikisini de destekleyebilirim, ancak B (Dosya dosyası) yapıcısının bulunmaması bir seçenek değildir. – Raniz

+2

Bana öyle geliyor ki senin sorunun, A'ların yapıcısı içindeki akışı tüketmekten kaynaklanıyor. Durum böyle olmasaydı, akışı bir örnek değişkeninde saklar ve A 'AutoClosable' yapardınız. –

cevap

25

Doğrudan kurucu kullanmak yerine statik bir fabrika yöntemi kullanmayı düşünün. Ancak burada ben değilim,

public class A { 
    protected A(){ 
     // so he can't be called from the outside, subclass ensure that init is done properly. 
    } 

    public A(InputStream stream) { 
     init(stream); 
    } 
    // not be able to call it from outside 
    protected final init(InputStream is){ 
     //here goes the code 
    } 
} 

public class B { 
    public B(File file) { 
     // We open the stream so we need to ensure it's properly closed 
     try (FileInputStream stream = new FileInputStream(file)) { 
      init(stream); 
     } 
    } 
} 

Muhtemel bir cevap olarak buraya ekliyorum.Böylece: En az B 'ın yapıcı gizli yap ve bir yöntem gibi

private B(InputStream is) { 
    super(is); 
    // Whatever else is needed 
} 

public static B newInstance(File file) { 
    B result; 
    try (FileInputStream stream = new FileInputStream(file)) { 
     result = new B(stream); 
    } 
    // Further processing 
    return result; 
} 
+0

Evet, işte bu şekilde gidiyor gibi görünüyor – Raniz

2

gitmek için başka bir yol oluşturmak consdering:

  1. Sen bir init yöntemi şantiye kodunu taşıyoruz
  2. A'nın kodunu güncelleyebilir, korumalı boş arg yapıcı sayesinde sadece alt sınıflar init için çağrıyı doğru bir şekilde kullanmalıdır. Bazıları bu kadar iyi tasarlanmadığını görebilir. Benim amacım, kısa bir süre sonra bir şeyleri alt sınıflara ayırmak, sadece onu kullandığınız zaman hakkında daha çok şey bilmek zorundasınız.
+0

* A * 'nın kaynak koduna erişim gerektirdiğini söylediniz ve * A *' da içeriğin içinden başlatılması gereken son değişkenler varsa çalışmayacaktır. akış – Raniz

+2

'init 'finali' yapmalısınız, aksi takdirde bir alt sınıf onu geçersiz kılabilir ve 'A' kurucusunu kırabilir. Sanırım buna inşaatçı sızıntısı denir ya da böyle bir şey. – Oebele

+0

iyi nokta ekledim. – Walfrat

-1

Ne yazık ki test etmek için elimde bir derleyici yok, ancak aşağıdakileri yapamaz mıydınız?

public class B { 
    private static InputStream file2stream(File f){ 
     // We open the stream so we need to ensure it's properly closed 
     try (FileInputStream stream = new FileInputStream(file)) { 
      return stream; 
     }catch(/*what you need to catch*/){ 
      //cleanup 
      // possibly throw runtime exception 
     } 
    } 
    public B(File file) { 
     super(file2stream(file)) 
    } 
} 
+3

Ne yazık ki, 'try' bloğunun sonuna' file2stream' sonundan önce ulaşılır, dosya 'super' içine geçirilmeden önce kapatılır. –

+0

Soruyu yanlış anlamış olabilirim, ama bunun önemli olduğunu düşündüm. Soruyu anlamaya çalışıyorum ki, denenerek korunan tek şey, eğer bu anlaşmanın nasıl anlaşılacağı gibi bir durum olmasaydı, InputStream'in inşasıydı. – lijat

+1

Hank D'nin yorumunu anlamıyorsunuz, bence. Sorun, kaynaklarla denemede, açılan kaynağın (akış) bloğun sonunda kapatılmasıdır.'Return' ifadesi bunu engellemez (ya da' try' için bir nokta olmaz). Yani, file2stream, kaynağı döndürdüğünde, ** zaten kapalı **. Ayrıca * kaynaklarla çalışmayı deneyin * (kaynakları kapatmak için yapılır) ve * istismarları yakalamak için yapılan * try-catch * arasındaki farkı not edin ve burada tartışılan konu değildir. – RealSkeptic