一、枚举类型——使用枚举类型分发

news/2024/11/30 7:47:17/

如果将 RoShamBo1.java 直接转换为基于枚举的实现版本,则会出现问题。因为枚举实例并不是类型,所以无法重载 eval() 方法,你无法将枚举实例作为参数类型。不过,还有别的方法可以利用枚举来实现多路分发。

一种方法是通过构造方法初始化每个枚举实例,并以一组结果作为参数,最终组成类似查询表的结构:

RoShamBo2.java

import static enums.TEST0006.Outcome.*;public enum RoShamBo2 implements Competitor<RoShamBo2> {PAPER(DRAW, LOSE, WIN),SCISSORS(WIN, DRAW, LOSE),ROCK(LOSE, WIN, DRAW);private Outcome vPAPER, vSCISSORS, vROCK;RoShamBo2(Outcome paper,Outcome scissors, Outcome rock) {this.vPAPER = paper;this.vSCISSORS = scissors;this.vROCK = rock;}@Overridepublic Outcome compete(RoShamBo2 it) {switch (it) {default:case PAPER:return vPAPER;case SCISSORS:return vSCISSORS;case ROCK:return vROCK;}}public static void main(String[] args) {RoShamBo.play(RoShamBo2.class, 20);}
}

Competitor.java

public interface Competitor<T extends Competitor<T>> {Outcome compete(T competitor);
}

Outcome.java

public enum Outcome {WIN, LOSE, DRAW}

RoShamBo.java

public class RoShamBo {public static <T extends Competitor<T>>void match(T a, T b) {System.out.println(a + " vs. " + b + ": " + a.compete(b));}public static <T extends Enum<T> & Competitor<T>>void play(Class<T> rsbClass, int size) {for (int i = 0; i < size; i++) {match(Enums.random(rsbClass), Enums.random(rsbClass));}}
}

Enums.java

import java.util.Random;public class Enums {private static Random rand = new Random(47);public static <T extends Enum<T>> T random(Class<T> ec) {return random(ec.getEnumConstants());}public static <T> T random(T[] values) {return values[rand.nextInt(values.length)];}
}

运行结果如下:

在这里插入图片描述

在 compete() 方法中,一旦两个类型都被确定了,那么唯一的动作就是返回得到的 outcome。然而,你也可以调用其他方法,甚至是(比如)构造方法中分配的命令对象中的方法。

RoShamBo2.java 比最初的版本更为简单明了,因此也更容易理解。注意,你仍然在使用两路分发来确定这两个对象的类型。在 RoShamBo1.java 中,两路的分发都是通过虚拟方法调用的。在这里,只有第一次分发使用了虚拟方法调用,第二次分发用的是 switch 。不过这样做是安全的,因为枚举限制了 switch 中的状态可选范围。

用来操作枚举的代码是独立的,因此也可以放到其他例子中使用。首先,Competitor(竞争者)接口定义了一个和另一个 Competitor 竞争的类型:

在这里插入图片描述

然后我们定义了两个静态方法(使用静态是为了避免显式地指定参数类型)。首先,match() 方法中调用了 compete() 方法,让两个 Competitor 竞争,可以看到此处类型参数只需要是 Competitor。但是在 play() 方法中,类型参数必须同时是 Enum(因为要放在Enuns.random()中使用)和 Competitor(因为要传给match()):

在这里插入图片描述

play() 方法没有将类型参数 T 作为返回值,因此,似乎你应该在 Class 中用通配符来取代主要的参数声明。然而通配符无法继承多个基类,因此我们必须使用上面的表达式。


http://www.ppmy.cn/news/580468.html

相关文章

Python爬虫框架Scrapy实战之抓取户外数据

一个户外论坛的特点: 列出一些活动&#xff0c;有翻页功能&#xff0c;点向一个活动显示当前活动信息&#xff0c;在二楼一般显示报名名单&#xff01; 需要的数据: 就是活动的信息&#xff0c;报名的名单&#xff0c;价钱&#xff0c;主题&#xff0c;url 数据库: 旅游表与报名…

五一户外装备品牌排行榜,列举几款性能高的户外装备

​“读万卷书&#xff0c;行万里路”&#xff0c;现在是个越来越多人喜欢户外活动的时代&#xff0c;毕竟工作压力大&#xff0c;生活节奏快&#xff0c;出去走走&#xff0c;释放一下工作的压力&#xff0c;是件很不错的事情。以前的人喜欢走到哪算哪&#xff0c;现在的人喜欢…

五一户外运动装备怎么选,列举出几款不错的户外装备

说到户外运动装备&#xff0c;大家想到的都是什么呢&#xff1f; 其实户外运动装备包括徒步登山、溯溪、攀岩、滑雪、自行车、单车运动、越野跑和皮划艇等。从这些运动的名称上可以看出&#xff0c;这些都是有一定危险性的&#xff0c;同时也需要一些专业的装备。徒步登山是户外…

osprey户外背包,助你玩虐三尖之行

有时候不徒步玩虐一把&#xff0c;真不知道自己还没老。这次徒步的线路我们选在了“华东第三虐”的三尖&#xff0c;这是相对通俗的一种叫法&#xff0c;近10座大小山峰的泛指&#xff0c;位于浙江省临安市西部。我们准备了三天时间&#xff0c;好好玩虐了一把三尖之行。 粮草…

户外防潮垫

转自&#xff1a;http://sports.ynet.com/view.jsp?oid55993938 说防潮垫是一个户外装备小品种&#xff0c;是因为它相对其他装备来说&#xff0c;它的价值较低&#xff0c;价格便宜。我们说它是一个不可忽视的品种&#xff0c;那是因为在户外相对严酷的条件下&#xff0c;解决…

差异化出圈之后,蕉下布局城市户外寻找“起跳”机会

出门即烫jio&#xff0c;被晒即变黑。 这个夏天&#xff0c;全国多地都开启了“热哭”模式&#xff0c;面对日渐强烈的阳光&#xff0c;防晒再次上演“刚需”热潮。 防晒霜、防晒喷雾、冰袖、防晒帽、遮阳伞...从化学防晒到物理防晒&#xff0c;人们选用的防晒方式多种多样。…

2020年全球及中国户外用品行业发展现状及竞争格局分析,高端市场被国外一线品牌垄断「图」

一、户外用品综述 户外运动用品行业的主要产品可分为服装类、鞋类、背包类、装备类、配件类和器材类&#xff0c;产品主要功能为在户外运动中为人体提供保护、装饰&#xff0c;并辅助运动进行。户外运动用品行业在欧美等发达国家拥有庞大的用户群体和市场基础&#xff0c;我国…

露营装备

帐篷 在野外露营&#xff0c;帐篷是我们通常想到的最重要的装备。包括快开宿营帐篷&#xff0c;家庭基地式宿营帐篷&#xff0c;登山宿营帐篷&#xff0c;遮阳篷/客厅帐/天幕帐等类别。 在购买帐篷前&#xff0c;需先明确宿营的人数&#xff0c;如是多人宿营&#xff0c;需要知…