外文翻译面向Java开发人员的Scala指南类操作.docx

上传人:b****7 文档编号:23606967 上传时间:2023-05-18 格式:DOCX 页数:17 大小:26.39KB
下载 相关 举报
外文翻译面向Java开发人员的Scala指南类操作.docx_第1页
第1页 / 共17页
外文翻译面向Java开发人员的Scala指南类操作.docx_第2页
第2页 / 共17页
外文翻译面向Java开发人员的Scala指南类操作.docx_第3页
第3页 / 共17页
外文翻译面向Java开发人员的Scala指南类操作.docx_第4页
第4页 / 共17页
外文翻译面向Java开发人员的Scala指南类操作.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

外文翻译面向Java开发人员的Scala指南类操作.docx

《外文翻译面向Java开发人员的Scala指南类操作.docx》由会员分享,可在线阅读,更多相关《外文翻译面向Java开发人员的Scala指南类操作.docx(17页珍藏版)》请在冰豆网上搜索。

外文翻译面向Java开发人员的Scala指南类操作.docx

外文翻译面向Java开发人员的Scala指南类操作

面向Java开发人员的Scala指南:

类操作

Java开发人员可以将对象作为理解Scala的出发点。

本文是面向Java开发人员的Scala指南系列的第二期,作者TedNeward遵循对一种语言进行评价的基本前提:

一种语言的威力可以直接通过它集成新功能的能力衡量,在本文中就是指对复数的支持。

跟随本文,您将了解在Scala中与类的定义和使用有关的一些有趣特性。

在上一期文章中,您只是稍微了解了一些Scala语法,这些是运行Scala程序和了解其简单特性的最基本要求。

通过上一篇文章中的HelloWorld和Timer示例程序,您了解了Scala的Application类、方法定义和匿名函数的语法,还稍微了解Array[]和一些类型推断方面的知识。

Scala还提供了很多其他特性,本文将研究Scala编程中的一些较复杂方面。

Scala的函数编程特性非常引人注目,但这并非Java开发人员应该对这门语言感兴趣的惟一原因。

实际上,Scala融合了函数概念和面向对象概念。

为了让Java和Scala程序员感到得心应手,可以了解一下Scala的对象特性,看看它们是如何在语言方面与Java对应的。

记住,其中的一些特性并不是直接对应,或者说,在某些情况下,“对应”更像是一种类比,而不是直接的对应。

不过,遇到重要区别时,我会指出来。

1.Scala和Java一样使用类

我们不对Scala支持的类特性作冗长而抽象的讨论,而是着眼于一个类的定义,这个类可用于为Scala平台引入对有理数的支持(主要借鉴自“ScalaByExample”,参见参考资料):

清单1.rational.scala

classRational(n:

Int,d:

Int)

{

privatedefgcd(x:

Int,y:

Int):

Int=

{

if(x==0)y

elseif(x<0)gcd(-x,y)

elseif(y<0)-gcd(x,-y)

elsegcd(y%x,x)

}

privatevalg=gcd(n,d)

valnumer:

Int=n/g

valdenom:

Int=d/g

def+(that:

Rational)=

newRational(numer*that.denom+that.numer*denom,denom*that.denom)

def-(that:

Rational)=

newRational(numer*that.denom-that.numer*denom,denom*that.denom)

def*(that:

Rational)=

newRational(numer*that.numer,denom*that.denom)

def/(that:

Rational)=

newRational(numer*that.denom,denom*that.numer)

overridedeftoString()=

"Rational:

["+numer+"/"+denom+"]"

}

从词汇上看,清单1的整体结构与Java代码类似,但是,这里显然还有一些新的元素。

在详细讨论这个定义之前,先看一段使用这个新Rational类的代码:

清单2.RunRational

classRational(n:

Int,d:

Int)

{

//...asbefore

}

objectRunRationalextendsApplication

{

valr1=newRational(1,3)

valr2=newRational(2,5)

valr3=r1-r2

valr4=r1+r2

Console.println("r1="+r1)

Console.println("r2="+r2)

Console.println("r3=r1-r2="+r3)

Console.println("r4=r1+r2="+r4)

}

清单2中的内容平淡无奇:

先创建两个有理数,然后再创建两个Rational,作为前面两个有理数的和与差,最后将这几个数回传到控制台上(注意,Console.println()来自Scala核心库,位于scala.*中,它被隐式地导入每个Scala程序中,就像Java编程中的java.lang一样)。

用多少种方法构造类?

现在,回顾一下Rational类定义中的第一行:

清单3.Scala的默认构造函数

classRational(n:

Int,d:

Int)

{

//...

您也许会认为清单3中使用了某种类似于泛型的语法,这其实是Rational类的默认的、首选的构造函数:

n和d是构造函数的参数。

Scala优先使用单个构造函数,这具有一定的意义——大多数类只有一个构造函数,或者通过一个构造函数将一组构造函数“链接”起来。

如果需要,可以在一个Rational上定义更多的构造函数,例如:

清单4.构造函数链

classRational(n:

Int,d:

Int)

{

defthis(d:

Int)={this(0,d)}

注意,Scala的构造函数链通过调用首选构造函数(Int,Int版本)实现Java构造函数链的功能。

2.实现细节

在处理有理数时,采取一点数值技巧将会有所帮助:

也就是说,找到公分母,使某些操作变得更容易。

如果要将1/2与2/4相加,那Rational类应该足够聪明,能够认识到2/4和1/2是相等的,并在将这两个数相加之前进行相应的转换。

嵌套的私有gcd()函数和Rational类中的g值可以实现这样的功能。

在Scala中调用构造函数时,将对整个类进行计算,这意味着将g初始化为n和d的最大公分母,然后用它依次设置n和d。

回顾一下清单1就会发现,我创建了一个覆盖的toString方法来返回Rational的值,在RunRational驱动程序代码中使用toString时,这样做非常有用。

然而,请注意toString的语法:

定义前面的override关键字是必需的,这样Scala才能确认基类中存在相应的定义。

这有助于预防因意外的输入错误导致难于觉察的bug(Java5中创建@Override注释的动机也在于此)。

还应注意,这里没有指定返回类型——从方法体的定义很容易看出——返回值没有用return关键字显式地标注,而在Java中则必须这样做。

相反,函数中的最后一个值将被隐式地当作返回值(但是,如果您更喜欢Java语法,也可以使用return关键字)。

3.一些重要值

接下来分别是numer和denom的定义。

这里涉及的语法可能让Java程序员认为numer和denom是公共的Int字段,它们分别被初始化为n-over-g和d-over-g;但这种想法是不对的。

在形式上,Scala调用无参数的numer和denom方法,这种方法用于创建快捷的语法以定义accessor。

Rational类仍然有3个私有字段:

n、d和g,但是,其中的n和d被默认定义为私有访问,而g则被显式地定义为私有访问,它们对于外部都是隐藏的。

此时,Java程序员可能会问:

“n和d各自的‘setter’在哪里?

”Scala中不存在这样的setter。

Scala的一个强大之处就在于,它鼓励开发人员以默认方式创建不可改变的对象。

但是,也可使用语法创建修改Rational内部结构的方法,但是这样做会破坏该类固有的线程安全性。

因此,至少对于这个例子而言,我将保持Rational不变。

当然还有一个问题,如何操纵Rational呢?

与java.lang.String一样,不能直接修改现有的Rational的值,所以惟一的办法是根据现有类的值创建一个新的Rational,或者从头创建。

这涉及到4个名称比较古怪的方法:

+、-、*和/。

与其外表相反,这并非操作符重载。

4.操作符

记住,在Scala中一切都是对象。

在上一篇文章中,您看到了函数本身也是对象这一原则的应用,这使Scala程序员可以将函数赋予变量,将函数作为对象参数传递等等。

另一个同样重要的原则是,一切都是函数;也就是说,在此处,命名为add的函数与命名为+的函数没有区别。

在Scala中,所有操作符都是类的函数。

只不过它们的名称比较古怪罢了。

在Rational类中,为有理数定义了4种操作。

它们是规范的数学操作:

加、减、乘、除。

每种操作以它的数学符号命名:

+、-、*和/。

但是请注意,这些操作符每次操作时都构造一个新的Rational对象。

同样,这与java.lang.String非常相似,这是默认的实现,因为这样可以产生线程安全的代码(如果线程没有修改共享状态——默认情况下,跨线程共享的对象的内部状态也属于共享状态——则不会影响对那个状态的并发访问)。

5.有什么变化

首先,您已经看到,函数可以作为对象进行操纵和存储。

这使函数具有强大的可重用性,本系列第一篇文章对此作了探讨。

第二个影响是,Scala语言设计者提供的操作符与Scala程序员认为应该提供的操作符之间没有特别的差异。

例如,假设提供一个“求倒数”操作符,这个操作符会将分子和分母调换,返回一个新的Rational(即对于Rational(2,5)将返回Rational(5,2))。

如果您认为~符号最适合表示这个概念,那么可以使用此符号作为名称定义一个新方法,该方法将和Java代码中任何其他操作符一样,如清单5所示:

清单5.求倒数

valr6=~r1

Console.println(r6)//shouldprint[3/1],sincer1=[1/3]

在Scala中定义这种一元操作符”需要一点技巧,但这只是语法上的问题而已:

清单6.如何求倒数

classRational(n:

Int,d:

Int)

{

//...asbefore...

defunary_~:

Rational=

newRational(denom,numer)

}

当然,需要注意的地方是,必须在名称~之前加上前缀“unary_”,告诉Scala编译器它属于一元操作符。

因此,该语法将颠覆大多数对象语言中常见的传统reference-then-method语法。

这条规则与“一切都是对象”规则结合起来,可以实现功能强大(但很简单)的代码:

清单7.求和

1+2+3//sameas1.+(2.+(3))

r1+r2+r3//sameasr1.+(r2.+(r3))

当然,对于简单的整数加法,Scala编译器也会“得到正确的结果”,它们在语法上是完全一样的。

这意味着您可以开发与Scala语言“内置”的类型完全相同的类型。

Scala编译器甚至会尝试推断具有某种预定含义的“操作符”的其他含义,例如+=操作符。

注意,虽然Rational类并没有显式地定义+=,下面的代码仍然会正常运行:

清单8.Scala推断

varr5=newRational(3,4)

r5+=r1

Console.println(r5)

打印结果时,r5的值为[13/12],结果是正确的。

6.Scala内幕

记住,Scala将被编译为Java字节码,这意味着它在JVM上运行。

如果您需要证据,那么只需注意编译器生成以0xCAFEBABE开头的.class文件,就像javac一样。

另外请注意,如果启动JDK自带的Java字节码反编译器(javap),并将它指向生成的Rational类,将会出现什么情况,如清单9所示:

清单9.从rational.scala编译的类

C:

\Projects\scala-classes\code>javap-private-classpathclassesRational

Compiledfrom"rational.scala"

publicclassRationalextendsjava.lang.Objectimplementsscala.ScalaObject{

privateintdenom;

privateintnumer;

privateintg;

publicRational(int,int);

publicRationalunary_$tilde();

publicjava.lang.StringtoString();

publicRational$div(Rational);

publicRational$times(Rational);

publicRational$minus(Rational);

publicRational$plus(Rational);

publicintdenom();

publicintnumer();

privateintg();

privateintgcd(int,int);

publicRational(int);

publicint$tag();

}

C:

\Projects\scala-classes\code>

Scala类中定义的“操作符”被转换成传统Java编程中的方法调用,不过它们仍使用看上去有些古怪的名称。

类中定义了两个构造函数:

一个构造函数带有一个int参数,另一个带有两个int参数。

您可能会注意到,大写的Int类型与java.lang.Integer有点相似,Scala编译器非常聪明,会在类定义中将它们转换成常规的Java原语int。

7.结束语

Scala将函数概念与简洁性相融合,同时又未失去对象的丰富特性。

从本系列中您可能已经看到,Scala还修正了Java语言中的一些语法问题(后见之明)。

本文是面向Java开发人员的Scala指南系列中的第二篇文章,本文主要讨论Scala的对象特性,使您可以开始使用Scala,而不必深入探究函数方面。

应用目前学到的知识,您现在可以使Scala减轻编程负担。

而且,可以使用Scala生成其他编程环境(例如Spring或Hibernate)所需的POJO。

原文出处:

thinkinjava

ThebusyJavadeveloper'sguidetoScala:

Classaction

ItmakessenseforJava™developerstouseobjectsasafirstpointofreferenceforunderstandingScala.InthissecondinstallmentofThebusyJavadeveloper'sguidetoScalaseries,TedNewardfollowsabasicpremiseoflanguagemeasurement:

thatthepowerofalanguagecanbemeasuredindirectrelationtoitsabilitytointegratenewfacilities--inthiscase,supportforcomplexnumbers.Alongthewayyou'llseesomeinterestingtidbitsrelatedtoclassdefinitionsandusageinScala.Inlastmonth'sarticle,yousawjustatouchofScala'ssyntax,thebareminimumnecessarytorunaScalaprogramandobservesomeofitssimplerfeatures.TheHelloWorldandTimerexamplesfromthatarticleletyouseeScala'sApplicationclass,itssyntaxformethoddefinitionsandanonymousfunctions,justaglimpseofanArray,andabitontype-inferencing.Scalahasagreatdealmoretooffer,sothisarticleinvestigatestheintricaciesofScalacoding.

Scala'sfunctionalprogrammingfeaturesarecompelling,butthey'renottheonlyreasonJavadevelopersshouldbeinterestedinthelanguage.Infact,Scalablendsfunctionalconceptsandobjectorientation.InordertolettheJava-cum-Scalaprogrammerfeelmoreathome,itmakessensetolookatScala'sobjectfeaturesandseehowtheymapovertoJavalinguistically.Bearinmindthatthereisn'tadirectmappingforsomeofthesefeatures,orinsomecases,the"mapping"ismoreofananalogthanadirectparallel.Butwherethedistinctionisimportant,I'llpointitout.

1.Scalahasclass(es),too

RatherthanembarkonalengthyandabstractdiscussionoftheclassfeaturesthatScalasupports,let'slookatadefinitionforaclassthatmightbeusedtobringrationalnumbersupporttotheScalaplatform(largelyswipedfrom"ScalaByExample"--seeResources):

Listing1.rational.scala

classRational(n:

Int,d:

Int)

{

privatedefgcd(x:

Int,y:

Int):

Int=

{

if(x==0)y

elseif(x<0)gcd(-x,y)

elseif(y<0)-gcd(x,-y)

elsegcd(y%x,x)

}

privatevalg=gcd(n,d)

valnumer:

Int=n/g

valdenom:

Int=d/g

def+(that:

Rational)=

newRational(numer*that.denom+that.numer*denom,denom*that.denom)

def-(that:

Rational)=

newRational(numer*that.denom-that.numer*denom,denom*that.denom)

def*(that:

Rational)=

newRational(numer*that.numer,denom*that.denom)

def/(that:

Rational)=

newRational(numer*that.denom,denom*that.numer)

overridedeftoString()=

"Rational:

["+numer+"/"+denom+"]"

}

WhiletheoverallstructureofListing1islexicallysimilartowhatyou'veseeninJavacodeoverthelastdecade,somenewelementsclearlyareatworkhere.Beforepickingthisdefinitionapart,takealookatthecodetoexercisethenewRationalclass:

Listing2.RunRational

classRational(n:

Int,d:

Int)

{

//...asbefore

}

objectRunRationalextendsApplication

{

valr1=newRational(1,3)

valr2=newRational(2,5)

valr3=r1-r2

valr4=r1+r2

Console.println("r1="+r1)

Console.println("r2="+r2)

Console.println("r3=r1-r2="+r3)

Console.println("r4=r1+r2="+r4)

}

WhatyouseeinListing2isn'tterriblyexciting:

Icreateacoupleofrationalnumbers,createtwomoreRationalsastheadditionandsubtractionofthefirsttwo,andechoeverythingtotheconsole.(NotethatConsole.println()comesfromtheScalacorelibrary,livinginscala.*,andisimplicitlyimportedintoeveryScalaprogram,justasjava.langisinJavaprogramming.)

HowmanywaysshallIconstructthee?

NowlookagainatthefirstlineintheRationalclassdefinition:

Listing3.Scala'sde

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1