Board logo

标题: C#不如Java的地方:静态导入 [打印本页]

作者: qingqing3721    时间: 2011-7-8 12:09     标题: C#不如Java的地方:静态导入

首先,请原谅我用了一个很土,很有争议的标题。小弟才思枯竭,实在想不出来什么文雅的了,抱歉~~  换了东家后,从一个死忠C# Fans摇身一变,客串了一把Java程序员,可能是受老赵的《Why Java Sucks》系列博文影响太大,刚开始那几天有很大的抵触情绪,后来想想,何不乘此机会深化理解一下Java。
  扮演Java程序员两个月以来,受到的折磨比拟多,由于以前习惯了微软的饭来张口,衣来伸手的战略,咋角色一转变还真有点不顺应,什么都得自己动手。虽然Java社区开源项目有数,框架一大把,但可能是选择太多就更迷茫,还是有点不顺应。
  我想写《Java超越C#的地方》这个系列文章,主要是抱着从一个C#程序员的角度,向Java学习的态度,决没有任何吵架的意思。吸取精髓,去其糟粕嘛,呵呵。当然,这个系列是不是写的下去,要看看我能否真的碰到了我觉得Java比C#好的地方,碰到了一个我就会记录一篇~~
  静态导入
  优点
  前言就说到这儿,现在进入今儿这篇文章的正题:静态导入(static import)。
  先看下面这段示例代码:

#div_code img{border:0px;}

Code highlighting produced by Actipro CodeHighlighter (freeware)CodeHighlighter/-->public class SayHelloTest{  @Test  public void should_say_hello_when_given_your_name(){gotoPage("hello");  input("name","yuyijq");  click("sayButton");   assertThat(helloPage.getLabel(),is("hello yuyijq")); }}

  这是一段典型的功用测试代码。关于功用测试来说,关键的就是要模拟用户场景,而不触及技术细节,用范围的语言来表达出测试。下面的测试用很明晰的步骤表达出了测试的意图,要注意的是这里的gotoPage,input,click以及assertThat方法都不是SayHelloTest类的实例方法,都是定义在别的类甚至是第三方框架中的静态方法。通过Java的静态导入特性,使得现在代码的可读性更高:

#div_code img{border:0px;}

Code highlighting produced by Actipro CodeHighlighter (freeware)CodeHighlighter/-->import static comblogs.yuyijq.functionalTest.gotoPage;

  弊端
  通过静态导入,我们可以去掉类名的前缀,这样就可以将代码写得更自然,更像是在描画一件事儿。但静态导入也并不是没有缺陷。在软件开发中,很多特性适当的使用都很好,但是一旦使用过度就有可能变成好事,这就是那个名言:不要拿着锤子,就把啥都当钉子。请看下面的代码:

#div_code img{border:0px;}

Code highlighting produced by Actipro CodeHighlighter (freeware)CodeHighlighter/-->map.get(MOST_VIEWED.toString()); map.get(LAST_VIEWED.toString()); map.get(IS_LAST_ARTICLE.toString()); map.get(IS_SHOW_PICTURE.toString());

  咋一看还以为这些MOST_VIEWED什么的全部是常量,但最后发现这些都是枚举PortalOptions里的项,都是通过静态导入导出去的。但由于没了PortalOptions这个具有说明信息的枚举名作为前缀,丧失了很多信息,形成这段代码不是很容易看懂,不知道map.get出来的究竟是什么。代码虽然短了很多,但是如果加上PortalOptions,那么就能很直观的直到我们需求从这个map里取得PortalOptions相关的东东。
  在C#里画瓢
  好的东西是要学习的,那我们如何在C#里照样画个瓢呢。可惜C#目前还不支持这种静态导入,我也没想到什么好法子能画这个瓢。在C#里不要类名或实例名这个前缀,那除非这个方法是本类的方法,但我们一定不可能为了使用这样的东东,就给每个类添加这些方法,不过C#里有一个扩展方法特性,我们看看是不是能用扩展方法来画这个瓢:

#div_code img{border:0px;}

Code highlighting produced by Actipro CodeHighlighter (freeware)CodeHighlighter/-->public static class UnitTestExtensions{  public static T mockT(this object o,Type mockType)  {return (T)NMock.Mock(mockType);}  }

  由于我们是给object类扩展的方法,所以在一切的类中都可以像是自己的方法一样使用,也就可以写下下面这样的代码了:

#div_code img{border:0px;}

Code highlighting produced by Actipro CodeHighlighter (freeware)CodeHighlighter/-->public class SayHelloControllerTest {  [Test]  public void should_load_user_when_given_username()  {  User user = new UserBuilder()  .withUserName("yuyijq")  .withAge(80)  .withSex(male) .build(); UserDAO userDAO = mock(typeof(UserDAO)); when(userDAO.findByUserName("yuyijq")).thenReturn(user); replay(userDAO); SayHelloController controller = new SayHelloController(userDAO); verify(userDAO);ModelAndView mv = controller.show("yuyijq"); assertModelAttribute(mv,"user",user); }}

  不过给object添加扩展方法实在不是一个好主意,净化太大了。目前也没有想出更好的方法,所以就此作罢~~
  后语
  静态导入就记叙到这里,两个月以来我还是对Java的语法五体投地,不过对Java社区对开源的采纳程度却是由衷的感叹。文章由斐格整理,收集辛苦,希望能保留出处,谢谢斑竹大哥。




欢迎光临 编程开发论坛 (http://bbs.lihuasoft.net/) Powered by Discuz! 6.0.0