這一節咱們轉向關注「方法/函數/操做」是如何定義的,即討論編程中的動詞,規約。html
行爲等價性就是站在客戶端的角度考量兩個方法是否能夠互換java
參考下述兩個函數:程序員
1 static int findFirst(int[] arr, int val) { 2 for (int i = 0; i < arr.length; i++) { 3 if (arr[i] == val) return i; 4 } 5 return arr.length; 6 } 7
8 static int findLast(int[] arr, int val) { 9 for (int i = arr.length - 1 ; i >= 0; i--) { 10 if (arr[i] == val) return i; 11 } 12 return -1; 13 }
findFirst
返回arr的長度,findLast
返回-1; findFirst
返回較低的索引,findLast
返回較高的索引。 static int findExactlyOne(int[] arr, int val) requires: val occurs exactly once in arr effects: returns index i such that arr[i] = val
兩個函數附和同一個規約,故兩者等價編程
【規約的結構】數組
【mutating methods(可變方法)的規約】app
規約評價的三個標準函數
【規約的肯定性】oop
肯定的規約:給定一個知足前置條件的輸入,其輸出是惟一的、明確的post
1 static int findExactlyOne(int[] arr, int val) 2 requires: val occurs exactly once in arr 3 effects: returns index i such that arr[i] = val
欠定的規約:同一個輸入能夠有多個輸出測試
1 static int findOneOrMore,AnyIndex(int[] arr, int val) 2 requires: val occurs in arr 3 effects: returns index i such that arr[i] = val
未肯定的規約:同一個輸入,屢次執行時獲得的輸出可能不一樣;但爲了不分歧,咱們一般將不是肯定的spec統必定義爲欠定的規約。
【規約的陳述性】
舉一個栗子:
static String join(String delimiter, String[] elements) effects : returns the result of adding all elements to a new : StringJoiner(delimiter) // Operational specs
effects:returns the result of looping through elements and alternately appending an element and the delimiter // Operational specs
effects: returns concatenation of elements in order, with delimiter inserted between each pair of adjacent elements // Declarative specs
【規約的強度】
舉一個栗子:
1 static int findExactlyOne(int[] a, int val) 2 requires: val occurs exactly once in a 3 effects: returns index i such that a[i] = val
1 static int findOneOrMore,AnyIndex(int[] a, int val) 2 requires: val occurs at least once in a 3 effects: returns index i such that a[i] = val
1 static int findOneOrMore,FirstIndex(int[] a, int val) 2 requires: val occurs at least once in a 3 effects: returns lowest index i such that a[i] = val
【如何設計一個好的規約】
【是否使用前置條件】