gpt4 book ai didi

java - 让实例变量的验证依赖于另一个实例变量是不好的做法吗?

转载 作者:行者123 更新时间:2023-12-02 01:01:30 26 4
gpt4 key购买 nike

让一个变量依赖于另一个变量的状态是不是很糟糕?

例如,我有一个类 Date,它具有属性 daymonthyear。月和年可以在各自的 setter 中独立验证,但day取决于和/或,即一个月内的最大天数/闰年。我的方法是确保我的构造函数需要所有三个字段,并且它将在 monthyear 之后调用 day 的 setter。

是否不鼓励这样的状态依赖?我的类不是不可变的,所以我需要某种验证,并且我想将验证封装在类本身中而不是在外部进行。

下面是我当前的代码:

   class Date {
private int day;
private int month;
private int year;

public String toString() {
return String.format("%02d/%02d/%04d", month, day, year);
}

public int getMonth() {
return month;
}

public void setMonth(int month) {
// Check if month is valid
if (month < 1 || month > 12) {
throw new IllegalArgumentException(
String.format("%02d is not a valid month", month)
);
} else {
this.month = month;
}
}

public int getYear() {
return year;
}

public void setYear(int year) {
// Check if year is valid
if (year < 1900 || year > 2020) {
throw new IllegalArgumentException(
String.format("%04d is not a valid year", year)
);
} else {
this.year = year;
}
}

public int getDay() {
return day;
}

public void setDay(int day) {
// Check if day is valid
if (day < 1 || day > getMaxNumDaysInMonth(this.getMonth(), this.getYear())) {
throw new IllegalAccessException(
String.format("%02d is not a valid day", day)
);
} else {
this.day = day;
}
}

Date(int month, int day, int year) {
setMonth(month);
setYear(year);
setDay(day);
}

private final int[] MAX_MONTH_DAYS = {
0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};

/**
* Gets the maximum number of days in a month
* Depends on the month and whether the year is a leap year
* @param month
* @param year
* @return
*/
private int getMaxNumDaysInMonth(int month, int year) {

// Check if date is valid
if (year < 1 || month < 1 || month > 12) {
throw new IllegalArgumentException(
String.format("%04d-%02d is not a valid date", year, month)
);
} else {
// Adjust February if year is a leap year
if (month == 2) {
if (isLeapYear(year)) {
return MAX_MONTH_DAYS[month];
} else {
return MAX_MONTH_DAYS[month] - 1;
}
} else {
return MAX_MONTH_DAYS[month];
}
}
} // end getNumDaysInMonth


/**
* Returns true if year is a Leap year
* Returns false otherwise
* @param year
* @return
*/
private boolean isLeapYear(int year) {
return (year % 4) == 0 && (year % 100 !=0 || year % 400 == 0);
}
} // end Date class

最佳答案

参数验证总是一个好主意,实际上有一些类专门为您做这种事情,并使其变得更加容易。

Preconditions

      public void setMonth(int month) {
Preconditions.checkArgument(month >= 1 && month <= 12, String.format("%s is not a valid month.", month));
this.month = month.
}

关于可变性的不相关注释

如果您希望此类不可变,但仍允许使用 setMonth 等方法,您始终可以将字段设置为最终字段,并返回一个新的日期,例如包含新月份的日期。

class Date {

private final int month;

private final int day;

private final int year;

// constructor

public Date setMonth(int month) {
// check argument is valid
return new Date(day, month, year);
}
}
Date date = new Date(2020, 3, 7);

date = date.setMonth(4);

您知道这已经完成了吗?

您需要创建一个管理日期的类吗?这已经存在,并且在过去几年中得到了极大的改进。

        LocalDate localDate = LocalDate.now();

localDate = localDate.withMonth(4).withDayOfMonth(8).withYear(2021);

LocalDateTime localDateTime = LocalDateTime.now();

localDateTime = localDateTime.withHour(9).withMinute(45).withSecond(30).withDayOfMonth(8);

ZonedDateTime zonedDateTime = ZonedDateTime.now();

zonedDateTime = zonedDateTime.withZoneSameLocal(ZoneId.of("UTC"));

关于java - 让实例变量的验证依赖于另一个实例变量是不好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60580815/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com