Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 有没有理由这样说;伪typedef反模式;?_Java_Typedef_Anti Patterns - Fatal编程技术网

Java 有没有理由这样说;伪typedef反模式;?

Java 有没有理由这样说;伪typedef反模式;?,java,typedef,anti-patterns,Java,Typedef,Anti Patterns,我有一个相对复杂的泛型类型(比如Map),我在类内部使用它。(没有外部可见性;这只是一个实现细节。)我想将其隐藏在typedef中,但Java没有这样的功能 昨天,我重新发现了下面这个成语,很失望地得知它的意思是 类MyClass { /*“伪类型定义”*/ 私有静态类FooBarMap扩展HashMap{}; FooBarMap[]地图; 公共FooBarMap getMapForType(int类型) { //实际代码可能比这更复杂 返回映射[类型]; } 公共字符串getDescript

我有一个相对复杂的泛型类型(比如
Map
),我在类内部使用它。(没有外部可见性;这只是一个实现细节。)我想将其隐藏在typedef中,但Java没有这样的功能

昨天,我重新发现了下面这个成语,很失望地得知它的意思是


类MyClass
{
/*“伪类型定义”*/
私有静态类FooBarMap扩展HashMap{};
FooBarMap[]地图;
公共FooBarMap getMapForType(int类型)
{
//实际代码可能比这更复杂
返回映射[类型];
}
公共字符串getDescription(int类型、长fooId、int-barId)
{
FooBarMap map=getMapForType(类型);
返回map.get(fooId).get(barId);
}
/*代码的其余部分*/
}

当类型被隐藏并且不是库API的一部分时(据我所知,这是Goetz使用它的主要反对意见),有什么理由可以这样做吗?

真正的问题是,这个习惯用法在伪typedef和客户机代码之间创建了高度耦合。但是由于您私下使用的是
FooBarMap
,因此耦合没有真正的问题(它们是实现细节)

NB


现代JavaIDE应该能够帮助处理复杂的泛型类型

对于公共接口,我不喜欢看到泛型类型,因为它们没有任何意义。对我来说,看到一个带有HashMap参数的方法很像foo(int,int,int,void*,int)等C方法。拥有一个真正的类型只会让代码更容易阅读。对于公共接口,最好创建封装HashMap而不是“typedef”的FooBarMap,但对于类内部使用,我看不到任何不利的一面。

如果没有这个伪typedef,我宁愿编写它

private Map<Long,Map<Integer,String>>[] maps;
私有地图[]地图;
如果有一天我决定将实现类从HashMap更改为TreeMap或Java7GreatEnhancedWonderfulMap:-),则不会有任何问题。但是有了这个,您就只能使用HashMap了。那么,你可以:

interface FooBarMap extends Map<Long,Map<Integer,String>> { };
class FooBarHashMap extends HashMap<Long,Map<Integer,String>> implements FooBarMap{ };
接口FooBarMap扩展了Map{};
类FooBarHashMap扩展HashMap实现FooBarMap{};

但是它变得越来越麻烦。

当涉及到将它放在公共界面时,他有一个很好的观点。这个习语是模仿某种形式的语法糖,它不应该影响您向客户展示的内容


但我认为没有理由不在本地使用它,前提是它让您的生活更轻松,代码更可读——而且您知道自己在做什么。Brian可能会在任何情况下概括并强烈反对它,但这是他的Goetz感觉:p

如果只在一个小的局部代码单元中使用它,那么问题很小,是真的

问题是,这样做的好处也是:在引用伪typedef 5次以上之前,您的程序可能甚至不会在文本上变小,这意味着它所在的区域必须是非平凡的


我可能不会重写这样做的代码,但这似乎是一个坏习惯。

在我看来,Java反模式的问题在于它们鼓励黑白思维

事实上,大多数反模式都有细微差别。例如,这篇链接文章解释了伪typedef如何导致API的类型签名过于严格,与特定的实现决策、病毒等联系过于紧密。但这一切都是在公共API的背景下进行的。如果将伪typedef排除在公共API之外(即,将它们限制在类或模块中),它们可能不会造成真正的伤害,并且可能会使代码更具可读性


我的观点是,您需要了解反模式,并对何时何地避免它们做出自己的理性判断。简单地说“我永远不会做X,因为它是一种反模式”意味着有时你会排除实用上可以接受的,甚至是好的解决方案。

不正确,因为示例中的类型是私有的,事实上,“typedef”路由保存了一些类型,因为您只需在代码中的一个位置替换Map->HashMap。如果我用类型Map声明字段,编译器将不允许我调用接口中未声明的方法。如果我用其他类实现映射替换实现类,那么所有代码都将继续工作。如果我将其声明为HashMap,我可以调用HashMap方法。在“typedef”中替换type将破坏代码。如果有一天我想使用Hibernate从DB加载地图,我可以这样做。如果我有HashMap,我必须新建并复制Hibernate提供的Map内容。强烈鼓励在任何可能的地方使用接口。这个习语不鼓励这样做。你称它为复杂的泛型类型?哈当我还是个孩子的时候,我们必须在凌晨3点起床处理六级递归嵌套泛型…是的。。。没有鞋子。。。上坡。。。雪中…@Marcus Downing:第七层是你在递归结束时在餐厅吃的早餐。;-)这种方法的问题是,客户端代码失去了映射数据结构的用处。如果不使用这种习惯用法,则会在长而复杂的类型描述(
HashMap
)和客户端代码之间创建高度耦合。你能解释一下为什么反模式的耦合比这更糟糕吗?@bacar问题是某人是否可以使用
HashMap
或你的
FooMap
。要使用接受
FooMap
的API,您不能传递HashMap。也就是说,如果在接口方法上声明,它们仅在一个方向上是多态的。前一个参数看起来像是在许多API中最好使用
byte[]
而不是
String
,但是选择
String
是有原因的,例如,不需要考虑字符编码和到处都是的东西。永远不允许用户使用专用地图
interface FooBarMap extends Map<Long,Map<Integer,String>> { };
class FooBarHashMap extends HashMap<Long,Map<Integer,String>> implements FooBarMap{ };