025:听闻你精通面向对象,来解决一下
#Quiz #Oop #Generic
计算机语言的进化之路走到2020年,面向对象与函数式乃是主流,每个语言模式的背后都是一套哲学与世界观。面向对象和函数式中最具力量的特性是泛型Generic,因其具有严谨的数学上的类型推导,从而使编写代码变得智能,健壮,使类型设计变得有趣而烧脑。
@史荣久 / 2020-11-18 / CC-BY-SA-3.0
1.经典问题
已知,苹果是水果的子类。 那么,装水果的水果袋与装苹果的苹果袋,
- 苹果袋是水果袋的子类么?
- 水果袋能否装苹果么?
- 要求用水果袋的地方,用苹果袋行么?
- 能用java泛型表示上述问题么?
2.综合场景
有一个解析控制台输入参数的方法,按空白
(0x20
和0x09
)分割命令行参数,支持String
和Number
(Long,Integer,Double,Float)两种类型。当使用单双引号('
和"
)括起来时,其内的字符串仅作为String
处理,也不考虑其内空白
。
示意代码如下。其意图是,希望通过传入参数的类型限定解析行为和输出类型。若传入String
时,各参数都当做String
处理,以List<String>
返回。若传入Object时,能自动解析Number
和String
类型参数,以List<Object>
返回。
@NotNull
public static <T> List<T> parseArgs(CharSequence line, Class<T> type) {
if (line == null || line.length() == 0) return Collections.emptyList();
List<T> args = new ArrayList<>();
StringBuilder buff = new StringBuilder();
for (int i = 0, len = line.length(); i < len; i++) {
// 分析`空白`分割的字符串,`引号`括起来的空白除外。
// 强制指定,引号括起来的字符串
typedAdd(args, buff, String.class);
// 自动识别,解析成Number或String
typedAdd(args, buff, Object.class);
}
if (buff.length() > 0) {
typedAdd(args, buff, Object.class);
}
return args;
}
private static void typedAdd(List<?> list, StringBuilder buff, Class<?> type) {
// 自动处理类型,并决定是否存入list中
buff.setLength(0);
}
@Test
public void testParseArgs() {
List<String> strs = parseArgs("123 456", String.class);
Assert.assertEquals(Arrays.asList("123", "456"), strs);
List<Object> objs = parseArgs("123 '456'", Object.class);
Assert.assertEquals(Arrays.asList(123, "456"), objs);
// 如果以CLass为参数,无法限定值,
// 可以使用Number.class, int[].class
// 无法控制程序行为和输出
}
■希望行为,优雅的利用面向对象和泛型知识
- 限定参数
type
的输入值,类似enum类特性,仅可输入2个固定值,Obj
和Str
- 当输入
Str
时,返回List<String>
,当Obj
时,返回List<Object>
- typedAdd方法支持泛型,不需要类型强转和SuppressWarnings
■核心思想,限制的艺术,把运行时错误消灭在编译时。
- 限定参数值,达到enum那种效果。
- 通过参数值,限定return类型。
■动手提示,
- 改造参数
Class<T> type
,当前无法约束参数值。 - 改造 typedAdd方法,目前无法完成真实功能。
–
※ 我们的征途是星辰大海 ※
题图:对象(含树),面向对象与函数式,是当今主流语言的共同特征