第七章、Groovy物件導向
1、定義類和指令碼
1.1、定義成員變數和本地變數
-
定義成員變數, 本地變數
-
/** * 宣告變數 * @author liangchen* @date 2020/11/8 */ class DeclareVariableDemo { // 成員變數 public fieldWithModifier String typedField def untypeField protected field1, field2, field3 private assignedField = new Date() static classField public static final String CONSTA = 'a', CONSTB = 'b' static void main(String[] args) { // ClassCastException 類轉換異常 final String PI = '3.14' assert PI.class.name == 'java.lang.String' assert PI.size() == 4 GroovyAssert.shouldFail(ClassCastException) { Float areaofCircleRadiusOne = PI } } def someMethods(){ // 本地變數 def localUntypedMethodVar = 1 int localTypedMethodVar = 1 def localVarWithoutAssigment , andAnotherOne } def localvar = 1,boundvar1 = 1 def someMethod(){ def localMethodVar = 1 boundvar2 = 1 } }
-
沒有欄位預設呼叫方法
-
/** * 引用成員變數 * @author liangchen* @date 2020/11/8 */ class ReferenceFieldDemo { static void main(String[] args) { def counter = new Counter() counter.count = 1 assert counter.count == 1 def fieldName = 'sum' counter[fieldName] = 2 assert counter.sum == 2 // 沒有值,就呼叫get方法 def pretender = new PretendFieldCounter() assert pretender.isNoField == 'pretend value' assert pretender.count == 0 //呼叫set方法 count ==1 pretender.isNoFieldEither = 'just to increase counter' // 呼叫set方法 count==2 pretender.aaa = 1 assert pretender.count == 2 } } class Counter{ public count =0 public sum = 0 } class PretendFieldCounter { public count = 0 Object get(String name) { return 'pretend value' } void set(String name, Object value) { count++ } }
1.2、定義方法和引數
-
可以是確定型別和不確定型別
-
/** * 宣告方法 和入參型別 * @author liangchen* @date 2020/11/8 */ class ClassWithTypedAndUntypedMethods { static void main(args) { def some = new ClassWithTypedAndUntypedMethods() some.publicVoidMethod() assert 'hi' == some.publicUntypedMethod() assert 'ho' == some.publicTypeMethod() def classWith = new ClassWithTypedAndUntypedMethodParams() // 入參型別 assert 'untyped' == classWith.method(1) assert 'typed' == classWith.method('whatever') assert 'two args' == classWith.method(1,2) } /** * 沒有返回值 */ void publicVoidMethod(){} /** * 沒有返回型別方法 * @return */ def publicUntypedMethod(){ return 'hi' } /** * 有返回值型別 * @return */ String publicTypeMethod(){ return 'ho' } private static final void combinedMethod(){} } class ClassWithTypedAndUntypedMethodParams { static void main(args) { } /** * 不確定型別入參 * @param arg * @return */ static method(arg){ return 'untyped' } /** * 有型別入參 * @param arg * @return */ static method(String arg) { return 'typed' } /** * 兩個引數 * @param arg1 * @param arg2 * @return */ static method(arg1, Number arg2) { return 'two args' } }
-
map, list 陣列入參
-
/** * list map 入參 * @author liangchen* @date 2020/11/9 */ class Summer { static void main(String[] args) { def summer = new Summer(); assert 2 == summer.sumWithDefualts(1,1) assert 3 == summer.sumWithDefualts(1, 1, 1) assert 2 == summer.sumWithList([1,1]) assert 3 == summer.sumWithList([1,1,1]) assert 2 == summer.sumWithOptionals(1,1) assert 3 == summer.sumWithOptionals(1,1,1) assert 2 == summer.sumNamed(a:1, b:1) assert 3 == summer.sumNamed(a: 1, b: 1, c: 1) assert 1 == summer.sumNamed(c:1) } def sumWithDefualts(a, b, c = 0) { return a + b + c } def sumWithList(List args) { return args.inject (0){sum, i -> sum +=i} } def sumWithOptionals(a, b, Object[] optionals) { return a + b + sumWithList(optionals.toList()) } /** * 入參為map * @param args * @return */ def sumNamed(Map args) { // 不存在設定0 ['a','b','c'].each {args.get(it, 0)} return args.a + args.b + args.c } }
-
1.3、?. 判斷是否連續為空 (短路運算子)
-
避免連續判空
-
/** * ?. 避免空指標,連續判空 * @author liangchen* @date 2020/11/9 */ class ProtectionNPEs { static void main(String[] args) { def map = [a: [b: [c: 1]]] assert map.a.b.c ==1 if (map && map.a && map.a.x) { assert map.a.x.c == null } try { assert map.a.x.c == null } catch (NullPointerException ignore) { } assert map?.a?.x?.c==null } }
-
1.4、構造器
-
指定成員變數名和其他方式
-
/** * @author liangchen* @date 2020/11/9 */ class CallConstructorDemo { String name, product CallConstructorDemo(name, product) { this.name = name this.product = product } // Java 的方式 def first = new CallConstructorDemo('Canoo', "ULC") // as 語法 def second = ['Canoo','ULC'] as CallConstructorDemo // 自己陣列元素 CallConstructorDemo third = ['Canoo', 'ULC'] } class CallConstructorNameDemo{ String name, product public static void main(String[] args) { // 可以指定成員變數名 new CallConstructorNameDemo() new CallConstructorNameDemo(name: 'Canoo') new CallConstructorNameDemo(product:'ULC') new CallConstructorNameDemo(name: 'Canoo', product: 'ULC') } }
-
2、組織類和指令碼
2.1、檔案與類關係
-
一個檔案有多個類
-
/** * 一個groovy 有兩個類 * @author liangchen* @date 2020/11/9 */ class MultipleClassDemo { static void main(String[] args) { def canoo = new Vendor() canoo.name = 'jack' canoo.product='apple' canoo.address.street = '天頂鄉' canoo.address.zip = 1121 canoo.address.town = '嶽麓區' canoo.address.state = '長沙' // 查詢匹配字元 assert canoo.dump() =~ /apple/ // 查詢匹配字元 assert canoo.address.dump() =~/1121/ println canoo.address.dump() } } class Vendor { public String name public String product public Address address =new Address(); } class Address{ public String street, town , state public int zip }
-
2.2、在包組織類
-
跟java類似
-
預設匯入語句
-
import java.lang.* import java.util.* import java.io.* import java.net.* import groovy.lang.* import groovy.util.* import java.math.BigInteger import java.math.BigDecimal
-
-
匯入設定別名 ( 避免相同類名,不同包下,識別更快)
-
需要繼承類
-
package com.jack.groovy.ch7.thirdparty /** * @author liangchen* @date 2020/11/10 */ class MathLib { Integer twice(Integer value) { return value * 3 } Integer half(Integer value) { return value / 2 } }
-
繼承類
-
package com.jack.groovy.ch7 // 這裡使用 as 為這個匯入設定別名 import com.jack.groovy.ch7.thirdparty.MathLib as TypeMathLib /** * @author liangchen* @date 2020/11/10 */ class MathLib extends TypeMathLib { /** * 訂正 2倍 * @param value * @return */ Integer twice(Integer value) { return value * 2 } static void main(String[] args) { def mathlib = new MathLib() assert 10 == mathlib.twice(5) assert 2 == mathlib.half(5) } }
-
-
2.3、考慮更深classpath(類路徑)
3、物件導向的高階特性
3.1、使用繼承
- 類似java
3.2、使用介面
- 類似java
3.3、多方法(過載)
-
方法名一樣,入參不一樣
-
/** * 方法過載 * @author liangchen* @date 2020/11/10 */ class Multimethod { def oracle(Object o) { return 'object' } def oracle(String o) { return 'string' } static void main(String[] args) { def multi = new Multimethod() Object x =1 Object y = 'foo' assert 'object' == multi.oracle(x) assert 'string' == multi.oracle(y) } }
3.4、使用trait
-
trait 關鍵字
-
/** * trait 有點類似 介面,只不過他有一些方法和屬性, 應該說是抽象類和介面結合體 * @author liangchen* @date 2020/11/10 */ class TraitDemo { trait HashId{ long id } trait HasVersion{ long version } trait Persistent{ boolean save(){ println "saving ${this.dump()}" } } trait Entity implements Persistent ,HashId, HasVersion{ boolean save(){ version++ Persistent.super.save() } } class Publication implements Entity{ String title } class Book extends Publication{ String isbn } static void main(String[] args) { Entity gina = new Book(id:1,version: 1,title: 'gina', isbn: "11111") gina.save() assert gina.version == 2 } }
4、GroovyBeans使用
4.1、宣告bean
-
/** * groovy bean 定義 * @author liangchen* @date 2020/11/10 */ class MyBeanDeom { static class MyBean implements Serializable{ String myprop //沒有定義型別 def untyped //定義型別 String typed def item1, item2 //賦值初始值 def assigned = 'default value' } static void main(String[] args) { MyBean myBean = new MyBean() assert 'default value' == myBean.getAssigned() myBean.setUntyped('some value') assert 'some value' == myBean.getUntyped() } }
4.2、beans執行特徵
-
獲取field(成員變數)和方法
-
/** * 呼叫groovy方法 * @author liangchen* @date 2020/11/10 */ class CallGroovyWayDemo { static class MrBean { String firstname, lastname String getName (){ return "$firstname $lastname" } } static void main(String[] args) { def bean = new MrBean(firstname: 'Rowan') bean.lastname = 'Jack' // 自動呼叫name --> getName 方法 assert 'Rowan Jack' == bean.name //獲取成員變數,使用.@ def beanss = new DoublerBean(value: 100) assert 200 == beanss.value assert 100 == beanss.@value } /** * 獲取成員變數,使用.@ * */ static class DoublerBean { public value void setValue(value) { this.value = value } def getValue() { value * 2 } } }
-
4.3、在任何類中使用bean 的方法
-
獲取def 修飾的field 欄位
-
/** * 獲取bean的屬性 * 獲取def 修飾的變數 * @author liangchen* @date 2020/11/10 */ class GDKBeanProperties { static class ClassWithProperties{ def someProperty public someField private somePrivateField } static void main(String[] args) { def obj = new ClassWithProperties() def store = [] obj.properties.each { property -> store += property.key store += property.value } assert store.contains('someProperty') assert store.contains('someField') == false assert store.contains('somePrivateField') == false assert store.contains('class') assert obj.properties.size() == 2 } }
-
4.4、Field、accessors、maps and Expando
-
Expando
-
/** * 動態擴充套件屬性和方法 Expando * @author liangchen* @date 2020/11/10 */ class ExpandoDemo { static void main(String[] args) { def boxer = new Expando() assert null == boxer.takeThis // 賦值 takeThis 不存在的值 boxer.takeThis = 'jack' assert 'jack' == boxer.takeThis // 定義方法 boxer.fightBack = {times -> delegate.takeThis * times} assert 'jackjack' == boxer.fightBack(2) } }
-
5、使用高階語法特性
5.1、使用GPaths查詢物件
-
/** * GPath 解析 * @author liangchen* @date 2020/11/10 */ class GPathInvoiceDemo { static class Invoice{ List items Date date } static class LineItem{ Product product int count int total(){ return product.dollar * count } } static class Product { String name def dollar } static void main(String[] args) { def ulcDate = Date.parse('yyyy-MM-dd', '2015-01-01') def otherDate = Date.parse('yyy-MM-dd', '2015-02-02') def ulc = new Product(dollar: 1499, name: 'ULC') def ve = new Product(dollar: 499, name: 'Visual Editor') def invoices = [ new Invoice(date: ulcDate, items: [ new LineItem(count: 5, product: ulc), new LineItem(count: 1, product: ve) ]), new Invoice(date: otherDate, items: [ new LineItem(count: 4, product: ve) ]) ] // lineItem 平鋪,拆開 def allItems = invoices.items.flatten() // 迴圈呼叫 total方法 assert [5*1499, 499, 4*499] == allItems*.total() // 查詢 數量大於 7000的 assert ['ULC'] == allItems.grep{it.total() > 7000}.product.name // product == ulc , date日期變成字串 def searchDates = invoices.grep { it.items.any{it.product == ulc}}.date*.toString() assert [ulcDate.toString()] == searchDates } }
5.2、注入*操作
-
/** * * 號操作 * @author liangchen* @date 2020/11/10 */ class SpreadDemo { def getList(){ return [1,2,3] } def sum(a, b, c) { return a + b + c } static void main(String[] args) { def spread = new SpreadDemo() // 直接呼叫getList 方法獲取到值作為sum的引數 assert 6 == spread.sum(*spread.list) // 直接使用*變數陣列 def range = (1..3) assert [0,1,2,3] == [0, *range] // 或者map 或者map *:map def map = [a:1, b:2] assert [a:1, b:2, c:3] == [c:3, *:map] } }
5.3、利用命令鏈來使用精確語法
6、總結
- 方法、成員變數、區域性變數定義(對比java來說的)
- groovybean定義
相關文章
- 物件導向-物件導向思想物件
- “程序導向”和“物件導向”物件
- 物件導向與程式導向物件
- 程式導向與物件導向物件
- 物件導向物件
- 物件導向,搞定物件物件
- JAVA物件導向基礎--物件導向介紹Java物件
- PHP 物件導向 (九)物件導向三大特徵PHP物件特徵
- Python物件導向Python物件
- [Java物件導向]Java物件
- Java物件導向Java物件
- Python 物件導向Python物件
- Java — 物件導向Java物件
- Python——物件導向Python物件
- 物件導向--下物件
- scala物件導向物件
- 物件導向(下)物件
- 物件導向(上)物件
- PHP物件導向PHP物件
- 物件導向 -- 反射物件反射
- JavaScript 物件導向JavaScript物件
- JS物件導向JS物件
- 物件導向(oop)物件OOP
- python-程式導向、物件導向、類Python物件
- Java物件導向——類與物件Java物件
- Js物件導向(1): 理解物件JS物件
- php中的程式導向與物件導向PHP物件
- JAVA物件導向思想Java物件
- [Java物件導向]finalJava物件
- Python物件導向(上)Python物件
- TypeScript與物件導向TypeScript物件
- 物件導向:繼承物件繼承
- 物件導向再探究物件
- 物件導向筆記物件筆記
- 物件導向-繼承物件繼承
- python物件導向(下)Python物件
- python物件導向一Python物件
- Java物件導向(一)Java物件