Skip to content

Commit 6302e96

Browse files
Merge pull request #1 from jxnu-liguobin/master
更新尝试
2 parents 5b145bd + 40a3e15 commit 6302e96

4 files changed

Lines changed: 198 additions & 15 deletions

File tree

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package cn.edu.jxnu.scala.basic
2+
3+
/**
4+
* 函数式对象即是:没有任何可变属性的对象
5+
*
6+
* @author 梦境迷离
7+
* @time 2018-12-17
8+
*/
9+
object FunctionObjects {
10+
11+
}
12+
13+
/**
14+
* ============================方法重载、重写、前置条件检查、隐式转换==============================
15+
*
16+
* n:分子
17+
* d:分母
18+
*
19+
* @see 《Scala编程》 P97
20+
*/
21+
class Rantional(val n: Int, val d: Int) {
22+
//给构造方法加前置条件
23+
require(d != 0)
24+
25+
// println(n + "/" + d) //构造对象时执行
26+
//重写非抽象方法,必须加override
27+
override def toString: String = n + "/" + d
28+
29+
def this(n: Int) {
30+
this(n, 1)
31+
}
32+
33+
//重载
34+
def *(that: Rantional): Rantional = new Rantional(that.n * n, that.d * d)
35+
36+
// 只是为了演示
37+
def *(i: Int): Rantional = new Rantional(n * i, d * i)
38+
39+
//重载
40+
def test() = "test"
41+
42+
//重载
43+
def test(name: String) = "test" + name
44+
45+
// implicit def intToRational(x: Int) = new Rantional(x) //定义在这里,下面访问不到
46+
}
47+
48+
object TestRantional extends App {
49+
val r = new Rantional(1, 2) // 打印1/2
50+
println(r)
51+
println("================定义操作符==============")
52+
// val a = new Rantional(1, 0) // 抛出IllegalArgumentException异常,构建对象失败
53+
val c = new Rantional(1, 2)
54+
val ret = r * c
55+
val ret1 = r.*(c)
56+
println(ret) // 输出1/4
57+
println(ret1) // 输出1/4
58+
println("================重载方法===============")
59+
println(ret.test("name"))
60+
println(ret.test)
61+
println("================隐式转换===============")
62+
val n = new Rantional(2, 2)
63+
println(n * 3) // 输出2*3/2*3 //这里不需要隐式转换等同 n.*(3)
64+
implicit def intToRational(x: Int) = new Rantional(x)
65+
66+
//可以定义隐式类,作为类型的转换
67+
println(3 * n) // 上面定义了隐式转换,不报错,否则3.*(n) 会提示3是Int没有*方法
68+
println(3.*(n)) //等同new Rantional(3,1)*Rantional(2,2)
69+
70+
/**
71+
* 隐式类
72+
* 在scala2.10后提供了隐式类,可以使用implicit声明类,但是需要注意以下几点:
73+
* 1.其所带的构造参数有且只能有一个
74+
* 2.隐式类必须被定义在类,伴生对象和包对象里
75+
* 3.隐式类不能是case class(case class在定义会自动生成伴生对象与2矛盾)
76+
* 4.作用域内不能有与之相同名称的标示符
77+
*
78+
* 转换前提
79+
* 1.不存在二义性(如例1)
80+
* 2.隐式操作不能嵌套使用,即一次编译只隐式转换一次(One-at-a-time Rule)
81+
* Scala不会把 x + y 转换成 convert1(convert2(x)) + y
82+
* 3.代码能够在不使用隐式转换的前提下能编译通过,就不会进行隐式转换。
83+
*
84+
* @param name
85+
*/
86+
implicit class implicitClass(val name: String) //隐式类必须用要有一个有一个参的主构造方法
87+
88+
89+
}

src/cn/edu/jxnu/scala/basic/CompanionClass.scala renamed to src/cn/edu/jxnu/scala/basic/ObjectsAndClasses.scala

Lines changed: 91 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@ package cn.edu.jxnu.scala.basic
99
class CompanionClass {
1010

1111

12-
private val str1 = "hello";
12+
private val str1 = "hello"
1313

1414
def print(): Unit = {
1515
println(CompanionClass.str2)
1616
}
1717

18-
18+
// 源文件名称可以和类名不同
1919
}
2020

21+
/**
22+
* ============================构造函数、实例化规则==============================================
23+
*/
2124
//伴生对象与伴生类同名,同一源文件中
2225
//注意单例对象是一等的,是特殊的class
2326
object CompanionClass extends App {
@@ -27,28 +30,28 @@ object CompanionClass extends App {
2730
//3.混入特质并重写main
2831
//继承/混入APP特质
2932
//单例可以混入特质
30-
private val str2 = "world";
33+
private val str2 = "world"
3134
val companionClass = new CompanionClass() //new只能实例化类
3235
println(companionClass.str1) //单例对象类似Java的static方法调用
3336
companionClass.print() //可以互相访问对方的私有属性,方法
3437

3538
}
3639

3740
class Construction {
38-
//class有主构造器和辅助构造器,辅助构造器第一行代码必须用调用主构造器
41+
//class有主构造器和辅助构造器,辅助构造器第一行代码须用调用主构造器(例外可以是:另一个调用了主构造的辅助构造)
3942
def this(var1: String) = {
4043
//无返回值类型
4144
this() //因为此时默认的主构造就是无参
4245
}
4346
}
4447

45-
//使用var表示在类的内部和外部均可以修改(因为生成字段var1,和var1的set方法)
48+
//使用var表示在类的内层和外层均可以修改(因为生成字段var1,和var1的set方法)
4649
//var1不使用val、var修饰则Scala不会为其生成字段以及访问器,只能暂时使用该变量
4750
class Construction2(var1: String, var2: String) {
4851
//类结构可以嵌入主构造,此时主构造就是2个参数
4952
//定义一个参数的辅助构造
5053
def this(var1: String) = {
51-
this(null, "hello") //同样需要第一行调用主构造
54+
this(null, "hello") //同样需要第一行调用主构造,或者是调用另一个出现在发起调用的构造方法之前的另一个辅助构造
5255
}
5356
}
5457

@@ -69,7 +72,7 @@ class Construction4 @SerialVersionUID(1L)(override val var1: String, override va
6972

7073
//1.java的super是静态绑定的
7174
//在java(单一继承)里面,假设有一个对象a,它既是类型X,又是类型Y,那么X和Y必定具有“父子关系”,也就是说,其中一个是另一个的父类。
72-
//因为java的继承是单一继承,不管实际类型是什么,一个对象的“继承链”,从super所在类开始往左的部分,都是在编译时期就可以确定下来的。
75+
//因为java的继承是单一继承,不管实际类型是什么,一个对象的“继承链”,从super所在类开始往左的层分,都是在编译时期就可以确定下来的。
7376
//2.scala的super是动态绑定的
7477
//在scala(多重继承)里面,假设有一个对象a,它既是trait X,又是trait Y, X和Y可能具有父子关系,也可能是共享同一个祖先的“兄弟”,反正,它们的关系不再限定在“父子”上。
7578
//因为scala允许多重继承,父亲类和trait们的优先顺序,是由对象的实际类型的线性化结果决定的,所以需要动态绑定。
@@ -88,3 +91,84 @@ class Construction4 @SerialVersionUID(1L)(override val var1: String, override va
8891

8992
}
9093

94+
//样例类的主构造必须得有参数
95+
//初始化可以省略new
96+
//因为默认自带equals、toString等。可以使用==比较,也可以使用println直接打印内容
97+
//match模式匹配时用的比较多
98+
//默认生成自己的伴生对象
99+
case class Construction5(name: String, pws: String = "pass")
100+
101+
object TestcaseClass extends App {
102+
103+
val jack = Construction5("name", "password")
104+
val rese = Construction5("name")
105+
println(jack, rese)
106+
val name = jack.name //样例类的实例内容可以直接打印
107+
println(jack.name == "name", rese == Construction5("name"))
108+
109+
}
110+
111+
/**
112+
* ==============================内层类,访问权限============================
113+
**/
114+
object OutPrivateClass extends App {
115+
116+
private val name: String = "hello"
117+
118+
// def getInnerName = println(InnerPrivateClass.innerName) //编译出差,禁止访问内层单例的私有
119+
120+
object InnerPrivateClass {
121+
122+
private val innerName: String = "hello"
123+
124+
def test() = print(name)
125+
}
126+
127+
InnerPrivateClass.test() //内层单例,可以读取外层单例的私有属性
128+
129+
}
130+
131+
class OutPrivateClass {
132+
//外层类别名,这之间不能有任何代码
133+
outer =>
134+
135+
class InnerPrivateClass2 {
136+
//访问内层类的私有,拒绝访问
137+
// private val innerName = "world"//
138+
//可以访问
139+
val innerName = "world"
140+
141+
def info() = println("访问外层类的私有属性试试:" + name)
142+
143+
// 在内层类通过【外层类.this.成员名称】 访问外层类成员
144+
def info1 = println("Outer name :" + OutPrivateClass.this.name + ",Inner Name :" + name)
145+
146+
//在内层类通过【外层类别名】 访问外层类成员
147+
def info2 = println("Outer name :" + outer.name + ",Inner Name :" + name)
148+
149+
}
150+
151+
// 访问内层类的私有,拒绝访问(即使你new了这个对象,你也无法得到私有属性,是非常严格的判定,与Java不同)
152+
// def getInnerName = new InnerPrivateClass2().innerName
153+
//可以访问
154+
def getInnerName = println("外层类访问内层类的属性:" + new InnerPrivateClass2().innerName)
155+
156+
// private val name: String = "hello" //下面方法均正常输出
157+
// val name: String = "hello" //下面方法均正常输出
158+
//限定具体的包的权限
159+
private[basic] val name: String = "hello" //下面方法均正常输出
160+
161+
162+
}
163+
164+
object TestInnerPrivateClass extends App {
165+
166+
val out1 = new OutPrivateClass()
167+
out1.getInnerName
168+
val inner1 = new out1.InnerPrivateClass2() //注意:Scala内层类是从属于外层类对象的。类似Java的static内部类的实例方式
169+
inner1.info()
170+
inner1.info1
171+
inner1.info2 //定义的时候不加括号,调用的时候就不能加
172+
173+
//PS:内部==内层==被嵌套类,外部==外层==嵌套类
174+
}
174 KB
Loading

src/cn/edu/jxnu/scala/basic/basicAndInfo.scala

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,18 +114,18 @@ package object basic {
114114
/**
115115
* 方法参数方法参数是在调用该方法时用于传递方法中的值的变量。
116116
* 方法参数只能从方法内部访问,但是如果从方法外部引用了对象,则可以从外部访问传入的对象。
117-
* 方法参数始终是不可变的,由val关键字定义。(这里有坑,val是隐式定义的,自己写的时候没有写val也是不可变
117+
* 方法参数始终是不可变的,由val关键字定义。(这里有坑,val是隐式定义的,自己写的时候没有写val也是不可变,函数每次调用的时候val有重写的值,所以val不能说是常量,绝对的常量应该加final)@see scala.math.Pi
118118
* 可变变量用var定义。应该尽量使用val @see Test3.scala
119-
*
120119
* 不能对数值进行++ --操作,Scala不支持 @see Test2.scala
121120
*
122121
*/
123122
/** 需要特别注意scala的访问权限
124123
* 1、访问控制符
125124
* Scala 访问修饰符基本和Java的一样,分别有:private,protected,public。
126125
* 如果没有指定访问修饰符符,默认情况下,Scala 对象的访问级别都是 public。
127-
* Scala 中的 private 限定符,比 Java 更严格,在嵌套类情况下,外层类不能访问被嵌套类的私有成员。
128-
* */
126+
* Scala 中的 private 限定符,比 Java 更严格,在嵌套类情况下,外层类不能访问被嵌套类的私有成员。(内部可以访问外层的私有,不如内部/层就没意义了。。。)
127+
* @see ObjectsAndClasses.scala->OutPrivateClass.scala | TestInnerPrivateClass.scala
128+
**/
129129

130130
/** 在 scala 中,对保护(Protected)成员的访问比 java 更严格一些。因为它只允许保护成员在定义了该成员的的类的子类中被访问。
131131
* 而在java中,用protected关键字修饰的成员,除了定义了该成员的类的子类可以访问,同一个包里的其他类也可以进行访问。
@@ -199,7 +199,8 @@ package object basic {
199199
* Scala的集合和映射(map) @see Test8.scala
200200
* Scala的可变集合主要用于命令式传统编程(当Java用),不可变主要用于函数式编程,推荐使用不可变,减少副作用,也更加安全 @see immutable.png、mutable.png
201201
* Scala从文件读取 @see IOExamples.scala、Test10.scala、Test11.scala
202-
* Scala 面向对象的类、单例对象、构造函数、序列化、注解使用等 @see CompanionClass.scala
202+
* Scala 面向对象的类、单例对象、构造函数、序列化、注解、重写、重载等 @see ObjectsAndClasses.scala FunctionObjects.scala
203+
* Scala基础语法图解 @see Scala语法图解.png (已经取得作者本人同意)
203204
**/
204205

205206
}
@@ -211,12 +212,21 @@ object Test1 {
211212
// scala 数组下标用(),泛型用[],@see Test3.scala
212213
def main(args: Array[String]) {
213214
println(apply(layout, 10))
215+
useLambda()
214216
}
215217

216218
// 函数 f 和 值 v 作为参数,而函数 f 又调用了参数 v
217219
def apply(f: Int => String, v: Int) = f(v)
218220

219221
def layout[A](x: A) = "[" + x.toString() + "]"
222+
223+
//声明一个lambda
224+
//实现对传入的两个参数进行凭借,lambda可以当做def使用
225+
val lambda = (param1: String, param2: String) => param1 + param2
226+
227+
def useLambda(): Unit = {
228+
println(lambda("hello", "world"))
229+
}
220230
}
221231

222232
object Test2 extends App {
@@ -260,8 +270,9 @@ object Test4 extends App {
260270
s toLowerCase; //无参,无副作用不用括号,使用后缀需要隔断,用分号
261271
println() //有副作用用括号
262272
var num = -1 //-是前缀操作符,实际也是方法调用 可用的前缀操作符:! + - ~ 都是一元的
263-
var num2 = 1.unary_-
264-
if (num == num2) println(true) //true 都是-1,Scala的==比较的是值的相等性,不同于Java的==(比较引用的地址或者基本类型的值)
273+
var num2 = 1.unary_- // unary_是混合操作符 yield在Scala是关键字,需要使用反引号`yield`,其他如match类似
274+
if (num == num2) println(true) //true 都是-1,Scala的==比较的是值的相等性,不同于Java的==(比较引用的地址或者基本类型的值),但是Scala的值比较自动处理null
275+
//且样例类可以直接使用值比较(==),因为样例类实现了很多譬如:equals、toString等方法 @T
265276
//若想要比较引用地址可用eq/ne方法,不过这只对Scala对象直接映射到Java对象的对象有效。比如String
266277
println("======================new eq=====================")
267278
val str1 = new String("hello")
@@ -272,7 +283,6 @@ object Test4 extends App {
272283
if (str1 == str2) println("==比较内容") //输出
273284
if (str1 equals str2) println("equals比较内容") //输出
274285
println("======================常量 eq=====================")
275-
276286
if (str3 eq str4) println("比较地址") //输出,指向同一个常量池的引用
277287
if (str3 == str4) println("==比较内容") //输出
278288
if (str3 equals str4) println("equals比较内容") //输出

0 commit comments

Comments
 (0)