在子类的重写方法中设置的Java类属性将丢失

时间:2012-10-08 22:28:05

标签: java polymorphism

我正在构建一个Android应用程序,并且已经设置了一个基础DBObject类来简化表格交互。 DBObject构造函数设置游标并将其传递给虚方法loadRecord,子类重写该方法以加载其自己的属性。根据loadRecord末尾的Log.i调用,这些属性都是正确的,但是一旦调用方法返回对象,所有数据成员都在类声明中定义了默认值,而不是加载的值(字符串为null) ,浮点数为0.00等。)

public abstract class DBObject {
....

    public DBObject(DBHelper dbh, String table_name, int _id){
        // loads an existing DBObject from the database by id
        this.dbh = dbh;
        this.TABLE_NAME = table_name;
        this.id = _id;
        setupDbr();
        String sql = String.format("select * from %s where _id=%d", TABLE_NAME, id);
        Cursor cur = dbr.rawQuery(sql, null);
        if (cur.getCount() == 0){
            throw new RowDoesNotExistException(id);
        } else if (cur.getCount() > 1){
            throw new RowDoesNotExistException("Record is not unique.", id);
        }
        cur.moveToFirst();
        loadRecord(cur);
    }
....
abstract void loadRecord(Cursor cur);

这个构造函数调用重写的loadRecord,它在子类中看起来像这样:

public class Expense extends DBObject{

    public String date = null;
    public String supplier = null;
    public String description = null;
    public float amount = 0.00f;
    public boolean receipt = false;

    public Expense(DBHelper dbh, String _id){
        super(dbh, DBHelper.EXPENSE_TABLE, _id);
...
    @Override
    void loadRecord(Cursor cur){
        id = cur.getInt(0);
        date = cur.getString(1);
        supplier = cur.getString(2);
        description = cur.getString(3);
        amount = cur.getFloat(4);
        receipt = (cur.getInt(5) == 1);
        Log.i("net.bradmont.reimburseit", String.format("%d, %s, %s, %s", id, date, supplier, description));
    }

在DBObject构造函数中设置的成员保持不变。我完全失去了这个......

提前致谢!

1 个答案:

答案 0 :(得分:2)

问题是你有实例变量初始值设定项:

public String date = null;
public String supplier = null;
public String description = null;
public float amount = 0.00f;
public boolean receipt = false;

初始化程序将在超类构造函数执行后执行子类构造函数的主体执行之前执行。这是在构造函数中调用重写方法的问题之一 - 这通常是一个非常糟糕的主意。

您可以通过不使用实例变量初始值设定项来解决此特定问题:

public String date;
public String supplier;
public String description;
public float amount;
public boolean receipt;

现在,超类构造函数完成和子类构造函数执行之间不会有额外的赋值。但是,它并不是一个非常好的解决方案 - 最好重新设计它以避免在超类构造函数中调用重写的方法。

我也试图摆脱公共领域......让它们变得私密,以避免暴露你班级的实施细节。

有关构造函数执行的详细信息,请参阅section 12.5 of the JLS