自从Java 8引入默认接口方法以来,我就觉得必须有一种方法来使用它来进行多重继承。所以决定尝试以下想法:
- 创建一个非公共类。
XData
要保存接口需要处理的字段,以及一个公共接口X
同X.java
源文件 - 接口有一个虚拟方法。
getXData()
返回XData
实例 - 其余的接口方法是默认的方法,这些方法调用
getXData()
根据需要读写字段,以执行一些有用的操作。 - 创建另一个接口
Y
和阶级YData
以同样的模式 - 创建一个类
XY
实现这两个接口的X
和Y
- 全班
XY
有XData
和YData
字段,这些字段由getXData()
和getYData()
。这是仅有的两个接口方法。XY
必须执行。 - 我没有在我的例子中费心,但是
XY
必须决定如何实现对象方法。hashCode
,equals
,和toString
。这些方法不能通过接口实现(但它们可以在XData
和YData
(如有需要的话)
最终的结果是XY
类的实例。X
和Y
接口,并继承两个接口的封装行为。X
和Y
默认方法-通过任何合理的措施进行多重继承。
它优于C++多重继承,因为所有构造函数逻辑和声明的字段都在XY
班级。你唯一能得到的问题是X
和Y
接口声明相同的方法,仅通过返回类型不同--但这只是实现多个接口的一个普遍问题。
下面是一些代码示例Dog
和Cow
接口。
Dog.java:
package mi;
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoField.HOUR_OF_DAY;
import static java.time.temporal.ChronoField.MINUTE_OF_DAY;
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
import static java.time.temporal.ChronoField.NANO_OF_SECOND;
import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
import static java.time.temporal.ChronoField.YEAR;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
/**
* The fields of data that Foo needs to operate on
*/
class DogData {
final String breed;
final String name;
final OffsetDateTime birthDate;
DogData(String breed, String name, OffsetDateTime birthDate) {
this.breed = breed;
this.name = name;
this.birthDate = birthDate;
}
}
public interface Dog {
/**
* The method the class has to implement to return a DogData instance, from one its own fields.
*
* @return dog data
*/
DogData getDogData();
/**
* Return the next time the dog should go to the vet for a checkup,
* which is annually, one week after the dog's birthday.
*
* @return date of next checkup.
*/
default OffsetDateTime nextCheckup() {
final OffsetDateTime now = OffsetDateTime.now();
final OffsetDateTime today = now.
minusHours(now.get(HOUR_OF_DAY)).
minusMinutes(now.get(MINUTE_OF_DAY)).
minusSeconds(now.get(SECOND_OF_MINUTE)).
minusSeconds(now.get(NANO_OF_SECOND));
final OffsetDateTime bday = getDogData().birthDate;
final int thisYear = now.get(YEAR);
final int bdayMonth = bday.get(MONTH_OF_YEAR);
final int bdayDay = bday.get(DAY_OF_MONTH);
OffsetDateTime nextCheckup = OffsetDateTime.
of(thisYear, bdayMonth, bdayDay, 12, 0, 0, 0, ZoneOffset.UTC).
plusDays(7);
if (nextCheckup.isBefore(today)) {
nextCheckup = nextCheckup.plusYears(1);
}
return nextCheckup;
}
default String getBreed() {
return getDogData().breed;
}
default String getName() {
return getDogData().name;
}
default OffsetDateTime getBirthDate() {
return getDogData().birthDate;
}
}
Cow.java:
package mi;
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoField.HOUR_OF_DAY;
import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
import static java.time.temporal.ChronoField.NANO_OF_SECOND;
import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
import static java.time.temporal.ChronoField.YEAR;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
class CowData {
String breed;
OffsetDateTime birthDate;
CowData(String breed, OffsetDateTime birthDate) {
this.breed = breed;
this.birthDate = birthDate;
}
}
public interface Cow {
/**
* The method the class has to implement to return a CowData instance, from one its own fields.
*
* @return cow data
*/
CowData getCowData();
/**
* Return the next time the cow should go to the vet for a shot,
* which is annually, one week before the cow's birthday.
*
* @return date of next checkup.
*/
default OffsetDateTime nextCheckup() {
final OffsetDateTime now = OffsetDateTime.now();
final OffsetDateTime today = now.
minusHours(now.get(HOUR_OF_DAY)).
minusMinutes(now.get(MINUTE_OF_HOUR)).
minusSeconds(now.get(SECOND_OF_MINUTE)).
minusNanos(now.get(NANO_OF_SECOND));
final OffsetDateTime bday = getCowData().birthDate;
final int thisYear = now.get(YEAR);
final int bdayMonth = bday.get(MONTH_OF_YEAR);
final int bdayDay = bday.get(DAY_OF_MONTH);
OffsetDateTime nextCheckup = OffsetDateTime.
of(thisYear, bdayMonth, bdayDay, 12, 0, 0, 0, ZoneOffset.UTC).
minusDays(7);
if (nextCheckup.isBefore(today)) {
nextCheckup = nextCheckup.plusYears(1);
}
return nextCheckup;
}
default String getBreed() {
return getCowData().breed;
}
default OffsetDateTime getBirthDate() {
return getCowData().birthDate;
}
}
DogCow.java:
package mi;
import static java.time.temporal.ChronoField.YEAR;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
public class DogCow implements Dog, Cow {
private final OffsetDateTime dogCowBdate = OffsetDateTime.of(
OffsetDateTime.now().get(YEAR) - (int)(Math.random() * 5),
(int)(Math.random() * 12) + 1,
(int)(Math.random() * 28) + 1,
(int)(Math.random() * 24),
(int)(Math.random() * 60),
0,
0,
ZoneOffset.UTC
);
private final DogData dogData = new DogData(
"Border Collie",
"Nate",
dogCowBdate
);
private final CowData cowData = new CowData(
"Angus",
dogCowBdate
);
@Override
public DogData getDogData() {
return dogData;
}
@Override
public CowData getCowData() {
return cowData;
}
@Override
public OffsetDateTime nextCheckup() {
// Check both Dog and Cow, choose whichever one comes first
final OffsetDateTime nextDogCheckup = Dog.super.nextCheckup();
final OffsetDateTime nextCowCheckup = Cow.super.nextCheckup();
return nextDogCheckup.isBefore(nextCowCheckup) ? nextDogCheckup : nextCowCheckup;
}
@Override
public String getBreed() {
return Dog.super.getBreed() + " " + Cow.super.getBreed();
}
@Override
public OffsetDateTime getBirthDate() {
return Dog.super.getBirthDate();
}
}
Main.java:
package mi;
public class Main {
public static void main(String[] args) {
for (int i = 1; i < 10; i++) {
final DogCow dc = new DogCow();
System.out.println(
"DogCow " + i +
" is combined breed " +
dc.getBreed() +
" named " +
dc.getName() +
" born on " +
dc.getBirthDate() +
" with next checkup of " +
dc.nextCheckup()
);
}
}
}
例Main.java产出:
DogCow 1 is combined breed Border Collie Angus named Nate born on 2022-11-22T21:40Z with next checkup of 2022-11-15T12:00Z
DogCow 2 is combined breed Border Collie Angus named Nate born on 2018-09-22T01:53Z with next checkup of 2022-09-15T12:00Z
DogCow 3 is combined breed Border Collie Angus named Nate born on 2022-01-26T18:08Z with next checkup of 2022-02-02T12:00Z
DogCow 4 is combined breed Border Collie Angus named Nate born on 2022-02-23T00:32Z with next checkup of 2022-03-02T12:00Z
DogCow 5 is combined breed Border Collie Angus named Nate born on 2019-03-27T04:24Z with next checkup of 2022-03-20T12:00Z
DogCow 6 is combined breed Border Collie Angus named Nate born on 2022-02-04T19:11Z with next checkup of 2022-02-11T12:00Z
DogCow 7 is combined breed Border Collie Angus named Nate born on 2020-02-20T17:13Z with next checkup of 2022-02-27T12:00Z
DogCow 8 is combined breed Border Collie Angus named Nate born on 2018-09-02T18:02Z with next checkup of 2022-08-26T12:00Z
DogCow 9 is combined breed Border Collie Angus named Nate born on 2018-01-07T21:02Z with next checkup of 2022-01-14T12:00Z
如果本文对你有所帮助别忘了给作者点个赞!