Bukan kelas Java yang melampirkan


366

Saya mencoba membuat game Tetris dan saya mendapatkan kesalahan kompiler

Shape is not an enclosing class

ketika saya mencoba membuat objek

public class Test {
    public static void main(String[] args) {
        Shape s = new Shapes.ZShape();
    }
}

Saya menggunakan kelas batin untuk setiap bentuk. Ini bagian dari kode saya

public class Shapes {
    class AShape {
    }
    class ZShape {
    }
}

Apa yang saya lakukan salah?


160
new Shape().new ZShape();. Kelas ZShapemembutuhkan instance yang dilampirkan untuk dipakai.
Sotirios Delimanolis

4
pindahkan kelas dalam untuk memisahkan file
Dimmduh

@Dimmduh komentar harus menjadi jawaban dalam kasus ini. Mereka seharusnya tidak menjadi kelas batin. Memindahkan mereka akan Mengidentifikasi masalah lain dengan kelas Bentuk yang ada.
Jeremiah Adams

Bukan untuk menjawab pertanyaan di sini tetapi dapatkah saya menyarankan untuk menggunakan warisan di sini di mana AShapedan ZShapememperluas kelas dasar Shapes. Kelas Nesting bukan desain yang benar-benar bagus untuk masalah ini.
Paramvir Singh Karwal

Jawaban:


492

ZShape tidak statis sehingga membutuhkan turunan dari kelas luar.

Solusi paling sederhana adalah membuat ZShape dan kelas bertingkat apa pun staticjika Anda bisa.

Saya juga akan membuat bidang apa pun finalatau static finalyang Anda bisa juga.


13
Membuat ZShape staticbenar-benar mengalahkan tujuan dari apa yang dia coba lakukan, yang merupakan contoh dari ZShape.
Cardano

17
@ Cardano membuatnya staticlebih mudah, bukan lebih keras.
Peter Lawrey

12
solusi sederhana lain adalah untuk membuat melampirkan kelas instantiate kelas batin, yaitu mendapatkan ZShape cara ini: ZShape myShape = new Shape().instantiateZShape();. Ini menyiratkan ZShape yang Anda dapatkan tidak ada tanpa Shape, yang maksudnya di sini.
Vince

@Peter Lawrey Bagaimana Anda menyadari bahwa semua instance Shape harus menggunakan ZShape yang sama? Saya tidak mendapatkannya dari sumbernya.
Jan

2
Ada 2 kasus jika kita ingin statis atau instance. Menjadikannya Statis tidak akan selalu membantu.
Yogesh Chuahan

177

Misalkan RetailerProfileModel adalah kelas utama Anda dan RetailerPaymentModel adalah kelas dalam di dalamnya. Anda bisa membuat objek kelas dalam di luar kelas sebagai berikut:

RetailerProfileModel.RetailerPaymentModel paymentModel
        = new RetailerProfileModel().new RetailerPaymentModel();

34
Jawaban ini sangat membantu, saya tidak pernah tahu Anda bisa menelepon baru dua kali berturut-turut (dan saya telah melakukan java selama 8+ tahun!)
PaulBGD

1
Anda pasti dapat menghubungi operator baru beberapa kali hingga Anda tidak ingin menyimpan referensi objek itu.
Vishal Kumar

1
Jika objek kelas dalam dibuat dengan cara ini, bagaimana cara mengakses anggota kelas luar?
Xingang Huang

1
Di dalam kelas dalam itu sendiri, Anda bisa menggunakan OuterClass.ini. Saya rasa tidak ada cara untuk mendapatkan instance dari luar kode kelas dalam. Tentu saja, Anda selalu dapat memperkenalkan properti Anda sendiri: getOuter OuterClass publik () {return OuterClass.this; }
Vishal Kumar

Bekerja untuk tes:underTest = Mockito.mock(Outer.class).new InnerNonStaticClass();
felvhage

48

Apa yang saya sarankan adalah tidak mengubah kelas non-statis ke kelas statis karena dalam kasus itu, kelas batin Anda tidak dapat mengakses anggota non-statis dari kelas luar.

Contoh:

class Outer
{
    class Inner
    {
        //...
    }
}

Jadi, dalam hal ini, Anda dapat melakukan sesuatu seperti:

Outer o = new Outer();
Outer.Inner obj = o.new Inner();

Bagaimana dengan Outer.Inner obj = (Outer baru). Inner baru ();
Hussain KMR Behestee

1
@ HusainKMRBehestee, tidak ada yang tidak akan berhasil. Namun, ini akan berhasilOuter.Inner obj = new Outer().new Inner();
Amit Upadhyay

Tapi Amit, itu berhasil untukku. Saya akan senang jika Anda bisa menjelaskan mengapa itu tidak berhasil.
Hussain KMR Behestee

1
@HussainKMRBehestee, penjelasan: Saya hanya bisa menebak bahwa tata bahasa di Jawa mengatakan bahwa untuk membuat instance kelas kita perlu memanggil konstruktor, dan sambil memanggil konstruktor ()adalah wajib. Namun, C, C ++ itu bukan keharusan. Ini adalah contoh yang tidak berfungsi. Apalagi saya menemukan posting ini . yang menjelaskan lebih lanjut tentang tata bahasa di Jawa dan bagaimana mereka diuraikan. Saya akan senang melihat contoh kasus ketika sintaks ini bekerja untuk Anda.
Amit Upadhyay

1
Oh, salahku, itu salah ketik, Outer.Inner obj = (new Outer ()). New Inner (); harap kali ini tidak apa-apa dan terima kasih telah memperhatikan itu.
Hussain KMR Behestee

18

Sebagaimana dinyatakan dalam dokumen :

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

Meskipun tautan ini dapat menjawab pertanyaan, lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini dan memberikan tautan untuk referensi. Jawaban hanya tautan dapat menjadi tidak valid jika halaman tertaut berubah. - Dari Ulasan
Muhammad Omer Aslam

Terima kasih! Baru memulai.
Brennan Miller

10

Terkadang, kita perlu membuat instance baru dari kelas dalam yang tidak bisa statis karena tergantung pada beberapa variabel global dari kelas induk. Dalam situasi itu, jika Anda mencoba membuat instance kelas dalam yang tidak statis, not an enclosing classkesalahan dilemparkan.

Mengambil contoh pertanyaan, bagaimana jika ZShapetidak bisa statis karena perlu variabel Shapekelas global ?

Bagaimana Anda bisa membuat instance baru ZShape? Begini caranya:

Tambahkan getter di kelas induk:

public ZShape getNewZShape() {
    return new ZShape();
}

Akses seperti ini:

Shape ss = new Shape();
ZShape s = ss.getNewZShape();


1

Saya mengalami masalah yang sama. Saya memecahkan dengan membuat contoh untuk setiap Kelas publik dalam. Adapun situasi Anda, saya sarankan Anda menggunakan warisan selain kelas batin.

public class Shape {

    private String shape;

    public ZShape zShpae;
    public SShape sShape;

    public Shape(){
      int[][] coords =  noShapeCoords;
      shape = "NoShape";
      zShape = new ZShape();
      sShape = new SShape();
    }

    class ZShape{
      int[][] coords =  zShapeCoords;
      String shape = "ZShape";
    }

    class SShape{
      int[][] coords = sShapeCoords;
      String shape = "SShape";
    }

 //etc
}

maka Anda dapat Bentuk baru (); dan kunjungi ZShape melalui shape.zShape;


1
Solusi yang salah. Kesalahan logis. Jika kelas dalam (mis. ZShape) membutuhkan bidang apa pun untuk diatur, di konstruktor kelas luar Anda harus mendapatkannya! Bentuk publik (String field1_innerClass, int field2_innerClass ...) {zShape = new ZShape (String field1_innerClass, int field2_innerClass ...) ...}}
Mohsen Abasi

1

Tidak perlu menjadikan kelas bersarang sebagai statis tetapi harus publik

public class Test {
    public static void main(String[] args) {
        Shape shape = new Shape();
        Shape s = shape.new Shape.ZShape();
    }
}

1

Satu hal yang saya tidak sadari pada awalnya ketika membaca jawaban yang diterima adalah bahwa membuat kelas internal statis pada dasarnya sama dengan memindahkannya ke kelas tersendiri.

Jadi, saat mendapat error

xxx bukan kelas penutup

Anda dapat menyelesaikannya dengan salah satu cara berikut:

  • Tambahkan statickata kunci ke kelas batin, atau
  • Pindahkan ke kelas tersendiri.

1

Dalam kasus jika kelas Induk adalah singleton gunakan cara berikut:

Parent.Child childObject = (Parent.getInstance()).new Child();

di mana getInstance()akan mengembalikan objek singleton kelas induk.


0

Untuk mencapai persyaratan dari pertanyaan, kita dapat menempatkan kelas ke dalam antarmuka:

public interface Shapes {
    class AShape{
    }
    class ZShape{
    }
}

dan kemudian gunakan seperti yang penulis coba sebelumnya:

public class Test {
    public static void main(String[] args) {
        Shape s = new Shapes.ZShape();
    }
}

Jika kita mencari solusi "logis" yang tepat, sebaiknya digunakan fabricpola desain

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.