Статикалық контекстте 'this' қолдануға болмайды

My aim is to have a class containing all functions which perform database operations cleanly and neatly - which can also be called with a single line of code, eg; DbFunctions.AddContact("fName", "lName");

Менде оқулықта оқыған DBAdapter класы бар:

public class DBAdapter {
static final String KEY_ROWID = "_id";
static final String KEY_NAME = "name";
static final String KEY_EMAIL = "email";
static final String TAG = "DBAdapter";

static final String DATABASE_NAME = "MyDB";
static final String DATABASE_TABLE = "contacts";
static final int DATABASE_VERSION = 1;

static final String DATABASE_CREATE =
        "create table contacts (_id integer primary key autoincrement, "
        + "name text not null, email text not null);";

final Context context;
DatabaseHelper DBHelper;
SQLiteDatabase db;

public DBAdapter(Context ctx)
{
    this.context = ctx;
    DBHelper = new DatabaseHelper(context);
}

private static class DatabaseHelper extends SQLiteOpenHelper
{
    DatabaseHelper(Context context)
    {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db)
    {
        try
        {
            db.execSQL(DATABASE_CREATE);
        }
        catch (SQLException ex)
        {
            ex.printStackTrace();
        }
    }
}

//---opens the database---
public DBAdapter open() throws SQLException
{
    db = DBHelper.getWritableDatabase();
    return this;
}

//---closes the database---
public void close()
{
    DBHelper.close();       
}   

// some other database functions here... inserts, updates etc
}

DBAdapter-ге барлық қоңырауларды өңдеу үшін өзімнің классымды жасадым:

    public static class DatabasesActivity extends Activity
{       
    static DBAdapter db;

   //Called when activity is first created
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public static long addContact(String name, String email)
    {
        if (db == null) {
            db = new DBAdapter(this);//<--- compiler error here
        }

        db.open();
        long id = db.insertContact("Joe Bloggs", "[email protected]");
        db.close();
        return id;
    }
}

addContact әдісінде, жолда: db = new DBAdapter (this); , келесі қатені аламын: Статикалық контекстте 'this' .

Мен OOP тұжырымдамасымен танысамын, сондықтан неге түсінемін? Мен осы қатені аламын, бірақ java-дің өзі үшін жаңа, мен өзіме қол жеткізуге тырысатын басқа әдістерді іздеймін. DBAdapter класс конструкторы context параметрінде қабылдайды, бірақ мен бұл сыныпты өзім жазғанымның себебін білмеймін.

Түсіндіру үшін: Мен қатенің пайда болу себебін білемін. DBAdapter класс конструкторы context параметрінде қабылдайды және оны статикалық түрде пайдаланған кезде мәтінмән параметрі ретінде қалай өту керектігін білмеймін. Мен сыныптың статикалық болуын қалаймын, себебі оны пайдаланғым келген сайын оны құрастырғым келмейді.

Менің ойымша, нақты мәселе «неге SQLiteOpenHelper контекст керек?»

1
@MarcoForberg Мен C# -де this сирек қолдандым. Пікіріңіз өте пайдалы емес.
қосылды автор Mike Baxter, көзі
@MarcoForberg Мен айтқанымдай; fair сомасы тек OK-ish сомасын C# кодын жазғанымды білдіреді. 6 айға жуық. Бұл менің сарапшы екенімді білдірмейді - мен де біреу боламын деп үміттенген жоқпын. Оның халқы сізге өте ұнайтын веб-сайтты толтыруды ұнатады.
қосылды автор Mike Baxter, көзі
@KlausByskovPedersen Егер сіз сұрақты дұрыс оқыған болсаңыз, мен статикалық және статистикалық емес айырмашылықты түсінемін - бұл қарапайым қарапайым екенін көресіз. Мен балама шешімдерді іздеймін, себебі мен java-нің өзі соншалықты таныс емеспін.
қосылды автор Mike Baxter, көзі
Бұл сұрақ соншалықты кең түрде түсіндірілгендіктен (менің мәселемді жеткілікті түрде түсіндірмегенім үшін өзімнің кінәмім) - мен мұнда жаңадан туындаған сұрақты жасадым. stackoverflow.com/questions/17234451/…
қосылды автор Mike Baxter, көзі
@Teifi ол жай ғана кодтау әдісін жасасаңыз, білу керек әдістер мен статикалық әдістер арасындағы айырмашылықты білу керек. Сіз айырмашылықты анық білмегендіктен, мен сізге 15 минут уақыт жұмсап, оны оқуды ұсынамын.
қосылды автор Klaus Byskov Pedersen, көзі
@Teifi, сондықтан түсініктеме және жауап жоқ. Мен оны өте жиі пайдаланатындықтан таңқалдырамын. кем дегенде бір сыныпта бір рет
қосылды автор Marco Forberg, көзі
Егер c ++ сияқты қате емес болсам, java бұл сөзді нақты жібермейді.
қосылды автор Infested, көзі

8 жауаптар

Мұнда static әдісін анықтадыңыз:

  public static long addContact(String name, String email)

Static methods and class variables are tied to the Class and not to any specific instance of the Class. You cannot use the this keyword inside it as it refers to the current instance. One of the choice will be to declare the method as instance method removing the static keyword from the method declaration, if indeed the method logic depends on the state of the current instance.

static әдісінің ішіндегі this әдісін пайдаланудағы проблема, сіздің кодыңыз статистикалық әдісті ClassName.staticMethodName() деп атаса, , бұл ретте осы уақыт аралығында this параметрін қалай шешу керектігі туралы ешқандай түсінік жоқ.

7
қосылды
DBAdapter конструкторы әдісі context параметрін қабылдайды және мен неге қажет екенін білмеймін. DBAdapter - үлгі коды. Егер сіз кез-келген жарық жасай аласыз болса, өтінеміз! :)
қосылды автор Mike Baxter, көзі
Менің сұрағымда айтқанымдай, мен неге қателесіп жатқанын түсінемін. Мен өз мақсатыма жетудің балама әдістерін іздеймін :)
қосылды автор Mike Baxter, көзі
@Teifi, әдіс ішінде неге this керек?
қосылды автор NINCOMPOOP, көзі

this refers to the current instance of that class.

Статикалық әдістер мен нысандар кез келген данадан тыс жерде бар, сондықтан сіз даналық деректерді қолдануға рұқсат берілмейді, мысалы, ағымдағы данамен, олардың ішінде

2
қосылды

бұл нысанға сілтегіш. Статикалық контекстте сізде нысан жоқ.

неге DatabaseActivy статикалық класс? Сондықтан қалыпты класс жасаңыз және оның нысанын жасаңыз

2
қосылды
@Birdy Мен осы дерекқор операцияларын кодтың бір жолымен орындауға мүмкіндік беретін класс жасамауға тырысамын. Мен оны пайдаланғым келетін кез келген уақытта сыныпты құрастырудан аулақ болуға тырысамын.
қосылды автор Mike Baxter, көзі
синглетонды үлгіні алуға қарағанда: theserverside.de/singleton-pattern-in-java
қосылды автор Birdy, көзі
Сілтегіш C ++ түсінігі. Сіз оны Java-де сілтеме деп атауыңыз керек.
қосылды автор Bruno Brant, көзі

Статикалық әдіс ішіндегі өрістерге немесе әдістерге кіре алмайсыз.

 Static methods do not point to any instance of the enclosing class.

Сондықтан this кілт сөзі сыныптың данасына қатысты.

In a static context:
you won't have instance reference to current instance.

Сондықтан қате пайда болады.

1
қосылды
Мен айтқанымдай, қателіктердің неге екенін түсінемін. Мен оны болдырмау үшін баламалы әдіс іздеймін. Мысалы, DBAdapter сыныбын ағымдағы context жолына өту арқылы қалай пайдалануға болады?
қосылды автор Mike Baxter, көзі
Сұрақ java :)
қосылды автор Mike Baxter, көзі
Сілтеме үшін мына жерден қараңыз, бірақ меніңше Android.See-де Android нұсқасы бар анонимдер бар :) Егер болмаса: stackoverflow.com/questions/2062520/…
қосылды автор ꜱᴜʀᴇꜱʜ ᴀᴛᴛᴀ, көзі
Жақсы, синглтон дизайнының үлгісіне барыңыз.Бұл жауап java.Бут Android-де маған біраз жеңіл жол керек, Бұл менің ниетім. :)
қосылды автор ꜱᴜʀᴇꜱʜ ᴀᴛᴛᴀ, көзі

Сіз мұны дұрыс емес статикалық функцияға қол жеткізесіз

Статикалық түрлендіргішті алып, функцияны статистикалық емес етіп жасаңыз, сонда ол жақсы жұмыс істейді

1
қосылды
Бірақ әдіс деп атағым келген кезден бастап, әрине, сыныпты құрастыру керек еді. Мен кодты тек бір жолды қолданып addContact әдісін шақыруға мүмкіндік беретін шешім іздеймін.
қосылды автор Mike Baxter, көзі
сіз не істей аласыз, сол сыныпта статикалық дананы жасайсыз және бұл статикалық дананы пайдаланып fucntion деп аталады ... бұл статикалық әдісті
қосылды автор Vikalp Jain, көзі

Осы әдіске қарап

// Called when activity is first created
@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

Статикалық класс, статикалық өріс және статикалық әдісті мүлде пайдаланбаңыз деп ойлаймын.

Әрекеттің мысалын жасап, онымен жұмыс жасаңыз. Егер сізде барлық бағдарлама арқылы бір әрекет нысанына қажет болса - Singleton Pattern қолданыңыз. Lazy және Жылдам жаңылыс мысалдары келтірілген.

мысалы инициализациялау қызық болады:

public class DatabaseActivity extends Activity {
private static final DatabaseActivity INSTANCE= new DatabaseActivity();

private DatabaseActivity() {}

public static DatabaseActivity getInstance() {
    return INSTANCE;
}

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);    //calls nonstatic method onCreate from Activity class
    setContentView(R.layout.activity_main);
} 
}
0
қосылды
Синглтон үлгісі кім?
қосылды автор Mike Baxter, көзі
менің жауапыма қосылды
қосылды автор Tala, көзі

Бұл статикалық контекстте «бұл» функциясын пайдалана алмайсыз, себебі ол сізде нысанның данасы бар және статикалық түрде даналарға қоңырау шала алмайсыз.

Неге статикалық сынып қажет?

0
қосылды

Сіз сыныпты статикалық етіп жасадыңыз.

Тек кірістірілген сыныптар статикалық болуы мүмкін. Осылайша сіз сыртқы сыныптың данасынсыз кірістірілген сыныпты пайдалана аласыз.

class OuterClass{
    public static class StaticNestedClass{
    }

    public class InnerClass{
    }

    public InnerClass getAnInnerClass(){
        return new InnerClass();
    }

    //This method doesn't work
    public static InnerClass getAnInnerClassStatically(){
        return new InnerClass();
    }
}

class OtherClass{
    //Use of a static nested class:
    private OuterClass.StaticNestedClass staticNestedClass = new OuterClass.StaticNestedClass();

    //Doesn't work
    private OuterClass.InnerClass innerClass = new OuterClass.InnerClass();

    //Use of an inner class:
    private OuterClass outerclass= new OuterClass();
    private OuterClass.InnerClass innerClass2 = outerclass.getAnInnerClass();
    private OuterClass.InnerClass innerClass3 = outerclass.new InnerClass();
}
0
қосылды