Java与构造函数中的参数传递混淆
我正在创建一个BMR计算器,我有一个名为User的类。此类包含用于计算BMR的所有方法,以及将用户数据(年龄、性别、体重、身高)打包在一起的构造函数 代码是:Java与构造函数中的参数传递混淆,java,variables,constructor,Java,Variables,Constructor,我正在创建一个BMR计算器,我有一个名为User的类。此类包含用于计算BMR的所有方法,以及将用户数据(年龄、性别、体重、身高)打包在一起的构造函数 代码是: public class User { int age; String gender; // todo: use an Enum double height; // height stored in cm, weight in kg (so if user enters in feet/lbs, conversions are done
public class User {
int age;
String gender; // todo: use an Enum
double height; // height stored in cm, weight in kg (so if user enters in feet/lbs, conversions are done to cm/kg and *THEN* passed through to constructor below)
double weight;
double activityMultiplier; // todo: use an Enum (possibly)
int bmr;
public User(int age, String gender, double height, double weight,
double activityMultiplier) {
this.age = age;
this.gender = gender;
this.height = height;
this.weight = weight;
this.activityMultiplier = activityMultiplier;
bmr = calcBMR();
}
/**
* If user input is correct, this method will calculate the BMR value of the user given their input and measurement choices.
*
* @param None
* @return BMR Value
*/
public int calcBMR() {
int offset = gender.equals("M") ? 5 : -161;
// This is the body of the calculations - different offset used depending on gender. Conversions to kg and cm done earlier so no conversions needed here.
// The formula for male and female is similar - only the offset is different.
return (int) (Math.round((10 * weight) + (6.25 * height) - (5 * age) + offset)); // This is the Miffin St-Jeor formula, calculations done in cm/kg
}
/**
* If the user selects the TDEE option, this method will be executed after the calcBMR() method.
* A value from the calcBMR() method will be passed down to this method, and is multiplied
* by the activity level parameter passed into this method.
*
* @param bmr (output from calcBMR() method
* @return TDEE Value
*/
public int calcTDEE(int bmr) {
return (int) Math.round(calcBMR() * activityMultiplier);
}
}
我担心的是,我不确定在构造函数(bmr=calcBMR()
)中初始化bmr值的方式是否正确。我无法计算bmr,直到用户的年龄、性别、身高和体重被记录并存储在变量中(上面5行就是这么做的)。这个编程结构可以吗?即,当创建用户对象时,年龄、性别、身高和体重存储在变量中,然后在构造函数中调用一个方法来计算和存储另一个值
有更好的方法吗?如果没有,我需要执行this.bmr=calcBMR()
还是bmr=calcBMR()
正常
注意,用户对象是在一个单独的类中创建的。我之所以感到困惑,主要是因为我没有将bmr参数传递给构造函数,而是使用方法返回值来初始化实例变量的值。语法上没有问题,但是不应该从构造函数调用可重写(公共/受保护的非最终)方法。如果有人覆盖它,它可能会破坏对象的构造。从构造函数调用helper方法很好,只需将其设置为私有或最终
this.bmr=calcBMR()
与
bmr=calcBMR()
说bmr.calcBMR()
没有意义,因为calcBMR
方法位于User
对象上bmr
是一个int
,因此它没有名为calcBMR
您是否使用此
取决于您的喜好。只有当您有一个名为bmr
的局部变量,然后显式调用实例变量而不是局部变量时,这才真正起作用。一般来说,使用相同名称的局部变量和实例变量很容易混淆
不过,您的calcTDEE
方法有点不合适。您可以只使用bmr
的值,而不传入或重新计算它,因此
public int calcTDEE() {
return (int) Math.round(bmr * activityMultiplier);
}
最好将计算与构造分开
我个人认为我们应该避免这样做。根据我的说法,任何使用类
构造对象
的人都不会意识到bmr
也在用户
中通过查看此特定构造函数进行计算,直到他查看代码为止。当您构建API
时,您应该让将要使用您的User
的消费者更易于阅读,除此之外,它是完全有效的。此外,正如所建议的,如果您不希望用户对象
s使用您的calcBMR
,您应该将其设置为私有
我想在这里补充一点,
bmr
是Person
的Health
相关参数之一,因此您应该在单独的类中收集所有此类参数,包括bodyFat
,bmr
,medicalAge
等,并将您的用户
对象
传递给该类的构造函数
。因此,Health
参数最终只能由有效的用户来构造。我认为您的方法是可以的。但是,如果您使用的所有属性都是“私有”的,并且具有get/set属性,则效果更好。所以,当另一个类扩展您的类时,我们不必担心混乱的事情。对于calcTDEE方法,我认为您只需要将bmr属性放入其中,因为它是在构造函数中设置的。因此,在调用此方法时,bmr具有正确的值
public int calcTDEE() {
return (int) Math.round(bmr * activityMultiplier);
}
希望这能有所帮助。谢谢你的评论。对不起,当我写
bmr.CalcBMR()
时,我的意思是bmr=CalcBMR
。编辑我的帖子。因此,您唯一的建议是将calcBMR()
方法设置为最终方法?这到底是做什么的?或者更可能的是,如果您只是从类内部调用它,则将其设置为私有。通过使它成为最终的或私有的,这意味着没有其他人可以改变它的行为。您可以创建一个覆盖calcBMR()的子类,然后更改您的计算(假设您不希望这样)。您还可以将其设置为私有,然后使用getBMR()方法,让人们只获取值。我假设您实际上不希望人们调用calcBMR(),您只希望他们获取值,对吗?是的,对。我唯一调用calcBMR()
我自己的地方是在构造函数中,主类只创建一个名为user1的用户对象,并将bmr引用为user1.bmr
。我将使这个方法私有,因为它只从用户类调用,听起来不错吧?谢谢:)事实上,我已经将其保留为公共
,但将其设置为最终版
,因此,如果需要修改代码,我仍然可以从BmrMain
类调用它。将final添加到方法签名中是否足够可行,以使其不可重写?除了Jeff的优点之外,我建议您将所有字段设置为私有,并为每个字段提供getter方法。如果没有这一点,外部代码可以在不重新计算bmr的情况下更改某些字段值。我喜欢这一建议,但我还没有准备好使用bodyfat计算器等。我想当我添加更多选项时,我只会将基础存储在User
类中,并创建另一个类,该类可以包含计算BMR、TDEE、体脂、宏(?)等的所有方法,以及可以存储值的构造函数。这就是你想说的吗?好的,你认为最好的方法是从Health
类调用方法(即calcBodyFat()
,calcBMR