Java中的多重继承

自从Java 8引入默认接口方法以来,我就觉得必须有一种方法来使用它来进行多重继承。所以决定尝试以下想法:

  • 创建一个非公共类。XData要保存接口需要处理的字段,以及一个公共接口X X.java源文件
  • 接口有一个虚拟方法。getXData()返回XData实例
  • 其余的接口方法是默认的方法,这些方法调用getXData()根据需要读写字段,以执行一些有用的操作。
  • 创建另一个接口Y和阶级YData以同样的模式
  • 创建一个类XY实现这两个接口的XY
  • 全班XYXDataYData字段,这些字段由getXData()getYData()。这是仅有的两个接口方法。XY必须执行。
  • 我没有在我的例子中费心,但是XY必须决定如何实现对象方法。hashCodeequals,和toString。这些方法不能通过接口实现(但它们可以在XDataYData(如有需要的话)

最终的结果是XY类的实例。XY接口,并继承两个接口的封装行为。XY默认方法-通过任何合理的措施进行多重继承。

它优于C++多重继承,因为所有构造函数逻辑和声明的字段都在XY班级。你唯一能得到的问题是XY接口声明相同的方法,仅通过返回类型不同--但这只是实现多个接口的一个普遍问题。

下面是一些代码示例DogCow接口。
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

如果本文对你有所帮助别忘了给作者点个赞!

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值