1 / 78

The essence of object-oriented programming

The essence of object-oriented programming. Programming Fundamentals 25 Feliks Klu ź niak. Consider conventional arithmetic expressions, defined by the following grammar: Expression = Term { ( “+” | “–” ) Term } .

nasnan
Download Presentation

The essence of object-oriented programming

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. The essence of object-oriented programming Programming Fundamentals 25 Feliks Kluźniak Essence of OOP

  2. Consider conventional arithmetic expressions, defined by the following grammar: Expression = Term { ( “+” | “–” ) Term } . Term = Factor { ( “*” | “div” | “mod” ) Factor } . Factor = Number | Identifier | “(“ Expression “)” . Number = [ “+” | “–” ] Digit { Digit } . Digit = “0” | “1” | “2” | “3” | “4” | “5” | “6” | “7” | “8” | “9” . Essence of OOP

  3. Consider conventional arithmetic expressions, defined by the following grammar: Expression = Term { ( “+” | “–” ) Term } . Term = Factor { ( “*” | “div” | “mod” ) Factor } . Factor = Number | Identifier | “(“ Expression “)” . Number = [ “+” | “–” ] Digit { Digit } . Digit = “0” | “1” | “2” | “3” | “4” | “5” | “6” | “7” | “8” | “9” . The following is an example of an expression: (2 + 1 – 4) * ( – (5 + 2) + 6) Essence of OOP

  4. Consider conventional arithmetic expressions, defined by the following grammar: Expression = Term { ( “+” | “–” ) Term } . Term = Factor { ( “*” | “div” | “mod” ) Factor } . Factor = Number | Identifier | “(“ Expression “)” . Number = [ “+” | “–” ] Digit { Digit } . Digit = “0” | “1” | “2” | “3” | “4” | “5” | “6” | “7” | “8” | “9” . The following is an example of an expression: (2 + 1 – 4) * ( – (5 + 2) + 6) A program that can process such expressions (e.g., evaluate them, or translate them to machine language …) would have a part called a parser (a.k.a., syntactic analyzer) that would convert each expression to a convenient internal format. Essence of OOP

  5. Consider conventional arithmetic expressions, defined by the following grammar: Expression = Term { ( “+” | “–” ) Term } . Term = Factor { ( “*” | “div” | “mod” ) Factor } . Factor = Number | Identifier | “(“ Expression “)” . Number = [ “+” | “–” ] Digit { Digit } . Digit = “0” | “1” | “2” | “3” | “4” | “5” | “6” | “7” | “8” | “9” . The following is an example of an expression: (2 + 1 – 4) * ( – (5 + 2) + 6) A program that can process such expressions (e.g., evaluate them, or translate them to machine language …) would have a part called a parser (a.k.a., syntactic analyzer) that would convert each expression to a convenient internal format. One such convenient internal format is that of a general tree (not a binary tree) that expresses the semantic (as opposed to syntactic) structure of the expression. Essence of OOP

  6. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 Essence of OOP

  7. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. Essence of OOP

  8. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. Essence of OOP

  9. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. Essence of OOP

  10. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. Essence of OOP

  11. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. Essence of OOP

  12. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. 2 Essence of OOP

  13. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. 1 2 Essence of OOP

  14. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. 3 1 2 Essence of OOP

  15. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. 3 4 Essence of OOP

  16. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. – 1 3 4 Essence of OOP

  17. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. – 1 Essence of OOP

  18. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. – 1 Essence of OOP

  19. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. – 1 Essence of OOP

  20. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. – 1 5 Essence of OOP

  21. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. – 1 5 2 Essence of OOP

  22. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. – 1 7 5 2 Essence of OOP

  23. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. – 1 – 7 Essence of OOP

  24. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. – 1 – 7 6 Essence of OOP

  25. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. – 1 – 1 – 7 6 Essence of OOP

  26. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 This form, often called an Abstract Syntax Tree, abstracts away from the details of the textual representation (in this case: parentheses) and explicitly represents the structure of the expression. It is, for instance, very easy to compute the value of the expression from this form. 1 – 1 – 1 Essence of OOP

  27. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 Let us try to write a function that would evaluate such a tree. We must first declare the appropriate types. There are three kinds of nodes: Essence of OOP

  28. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 21 + 5 2 Let us try to write a function that would evaluate such a tree. We must first declare the appropriate types. There are three kinds of nodes: Value nodes, which represent integers. Essence of OOP

  29. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 Let us try to write a function that would evaluate such a tree. We must first declare the appropriate types. There are three kinds of nodes: Value nodes, which represent integers. UnOp nodes, which represent applications of unary operators. Essence of OOP

  30. (2 + 1 – 4) * ( – (5 + 2) + 6) * –+ + 4 – 6 2 1 + 5 2 Let us try to write a function that would evaluate such a tree. We must first declare the appropriate types. There are three kinds of nodes: Value nodes, which represent integers. UnOp nodes, which represent applications of unary operators. BinOp nodes, which represent applications of binary operators. Essence of OOP

  31. (2 + 1 – 4) * ( – (5 + 2) + 6) * – + + 4 – 6 2 1 + 5 2 Let us try to write a function that would evaluate such a tree. We must first declare the appropriate types. There are three kinds of nodes: Value nodes, which represent integers. UnOp nodes, which represent applications of unary operators. BinOp nodes, which represent applications of binary operators. The main difference between them is in the number of children: a Value node has no children, a UnOp node has one and a BinOp node has two.

  32. We must first declare the appropriate types. There are three kinds of nodes: Value nodes, which represent integers. UnOp nodes, which represent applications of unary operators. BinOp nodes, which represent applications of binary operators. The main difference between them is in the number of children: a Value node has no children, a UnOp node has one and a BinOp node has two. Essence of OOP

  33. We must first declare the appropriate types. There are three kinds of nodes: Value nodes, which represent integers. UnOp nodes, which represent applications of unary operators. BinOp nodes, which represent applications of binary operators. The main difference between them is in the number of children: a Value node has no children, a UnOp node has one and a BinOp node has two. The operators themselves can be encoded as integers, for example: constop_add = 0; % addition (+) constop_sub = 1; % subtraction (–) constop_mult = 2; % multiplication (*) constop_div = 3; % division (div) constop_mod = 4; % modulo (mod) constop_plus = 5; % unary plus (+) constop_minus = 6; % unary minus (–) Essence of OOP

  34. Value nodes, which represent integers. UnOp nodes, which represent applications of unary operators. BinOp nodes, which represent applications of binary operators. type Value = record% An integer value: val : int% the value end Essence of OOP

  35. Value nodes, which represent integers. UnOp nodes, which represent applications of unary operators. BinOp nodes, which represent applications of binary operators. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ?% the operand end ; typeBinOp = record% A binary operator: op : int; % the operator opnd1 : ? ; % the left operand opnd2 : ?% the right operand end Essence of OOP

  36. Value nodes, which represent integers. UnOp nodes, which represent applications of unary operators. BinOp nodes, which represent applications of binary operators. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ?% the operand end ; typeBinOp = record% A binary operator: op : int; % the operator opnd1 : ? ; % the left operand opnd2 : ?% the right operand end What should be the types of the pointers to children? Essence of OOP

  37. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ? % the operand end ; typeBinOp = record% A binary operator: op : int; % the operator opnd1 : ? ; % the left operand opnd2 : ?% the right operand end What should be the types of the pointers to children? Notice that the operand of a unary operator might be a Value, a UnOp, or a BinOp ! Essence of OOP

  38. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ? % the operand end ; typeBinOp = record% A binary operator: op : int; % the operator opnd1 : ? ; % the left operand opnd2 : ?% the right operand end What should be the types of the pointers to children? Notice that the operand of a unary operator might be a Value, a UnOp, or a BinOp ! So, we have a problem! Essence of OOP

  39. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ? % the operand end ; typeBinOp = record% A binary operator: op :int; % the operator opnd1 : ? ; % the left operand opnd2 : ?% the right operand end What should be the types of the pointers to children? Notice that the operand of a unary operator might be a Value, a UnOp, or a BinOp ! So, we have a problem! This problem is typical of heterogenous data structures, where the elements are similar in some respects, but different in others. Essence of OOP

  40. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ? % the operand end ; typeBinOp = record% A binary operator: op :int; % the operator opnd1 : ? ; % the left operand opnd2 : ?% the right operand end What should be the types of the pointers to children? Notice that the operand of a unary operator might be a Value, a UnOp, or a BinOp ! So, we have a problem! This problem is typical of heterogenous data structures, where the elements are similar in some respects, but different in others. Consider, e.g., a structure that contains information about families of people. Some of them will be new-born babies, some will be students, some self-employed etc. Essence of OOP

  41. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ? % the operand end ; typeBinOp = record% A binary operator: op :int; % the operator opnd1 : ? ; % the left operand opnd2 : ?% the right operand end What should be the types of the pointers to children? Notice that the operand of a unary operator might be a Value, a UnOp, or a BinOp ! So, we have a problem! This problem is typical of heterogenous data structures, where the elements are similar in some respects, but different in others. Consider, e.g., a structure that contains information about families of people. Some of them will be new-born babies, some will be students, some self-employed etc. All of them will have some common characteristics (name, date of birth …), Essence of OOP

  42. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ? % the operand end ; typeBinOp = record% A binary operator: op :int; % the operator opnd1 : ? ; % the left operand opnd2 : ?% the right operand end What should be the types of the pointers to children? Notice that the operand of a unary operator might be a Value, a UnOp, or a BinOp ! So, we have a problem! This problem is typical of heterogenous data structures, where the elements are similar in some respects, but different in others. Consider, e.g., a structure that contains information about families of people. Some of them will be new-born babies, some will be students, some self-employed etc. All of them will have some common characteristics (name, date of birth …), many will also have information that is relevant only to the particular kind of person (GPA for students, place of employment for adults who are not self-employed ….). Essence of OOP

  43. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ? % the operand end ; typeBinOp = record% A binary operator: op :int; % the operator opnd1 : ? ; % the left operand opnd2 : ?% the right operand end What should be the types of the pointers to children? Notice that the operand of a unary operator might be a Value, a UnOp, or a BinOp ! There are three common ways to solve the problem. Essence of OOP

  44. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ? % the operand end ; type BinOpP = BinOp ^ ; typeBinOp = record% An operator or a value: kind : int; % kind of node op :int;% the operator or the value opnd1 : BinOpP ;% the left operand, if any opnd2 : BinOpP% the right operand, if any end The first is to have only one type of record that will contain fields that are not always used. In our case this would be the BinOp record: by convention, when representing a unary operator we would not use the opnd2 field, and when representing a value we would use just the op field for storing the value. Essence of OOP

  45. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ? % the operand end ; type BinOpP = BinOp ^ ; typeBinOp = record% An operator or a value: kind : int; % kind of node op : int;% the operator or the value opnd1 : BinOpP ;% the left operand, if any opnd2 : BinOpP% the right operand, if any end The first is to have only one type of record that will contain fields that are not always used. In our case this would be the BinOp record: by convention, when representing a unary operator we would not use the opnd2 field, and when representing a value we would use just the op field for storing the value. What are the disadvantages of such a scheme? Essence of OOP

  46. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ? % the operand end ; type BinOpP = BinOp ^ ; typeBinOp = record% An operator or a value: kind : int; % kind of node op : int;% the operator or the value opnd1 : BinOpP ;% the left operand, if any opnd2 : BinOpP% the right operand, if any end The first is to have only one type of record that will contain fields that are not always used. In our case this would be the BinOp record: by convention, when representing a unary operator we would not use the opnd2 field, and when representing a value we would use just the op field for storing the value. The disadvantages of such a scheme: wasted space (not serious here, could be serious in other applications) Essence of OOP

  47. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ? % the operand end ; type BinOpP = BinOp ^ ; typeBinOp = record% An operator or a value: kind : int; % kind of node op : int;% the operator or the value opnd1 : BinOpP ;% the left operand, if any opnd2 : BinOpP% the right operand, if any end The first is to have only one type of record that will contain fields that are not always used. In our case this would be the BinOp record: by convention, when representing a unary operator we would not use the opnd2 field, and when representing a value we would use just the op field for storing the value. The disadvantages of such a scheme: wasted space (not serious here, could be serious in other applications); we have to be very careful to keep our program consistent: there is no help from the compiler, we must just describe our convention and try to stick to it. Essence of OOP

  48. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ? % the operand end ; typeBinOp = record% A binary operator: op :int; % the operator opnd1 : ? ; % the left operand opnd2 : ? % the right operand end Notice that the operand of a unary operator might be a Value, a UnOp, or a BinOp ! The second approach is to have a facility for declaring a discriminated union type (C), a.k.a. a record with variants (Pascal). The idea is that one can declare that various groups of fields are alternatives, i.e., can never occur together. There is also a tag field that can be used to indicate which of the alternatives is the right one. Essence of OOP

  49. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ? % the operand end ; typeBinOp = record% A binary operator: op :int; % the operator opnd1 : ? ; % the left operand opnd2 : ? % the right operand end Notice that the operand of a unary operator might be a Value, a UnOp, or a BinOp ! The second approach is to have a facility for declaring a discriminated union type (C), a.k.a. a record with variants (Pascal). The idea is that one can declare that various groups of fields are alternatives, i.e., can never occur together. There is also a tag field that can be used to indicate which of the alternatives is the right one. For example, in Pascal: type Exp = record case arity : intof 0 : (val : int ); 1 : (op : int, opnd : ExpP ) 2 : (op : int, opnd1, opnd2 : ExpP ) end

  50. type Value = record% An integer value: val : int% the value end ; typeUnOp = record % A unary operator: op : int; % the operator opnd : ? % the operand end ; typeBinOp = record% A binary operator: op :int; % the operator opnd1 : ? ; % the left operand opnd2 : ? % the right operand end Notice that the operand of a unary operator might be a Value, a UnOp, or a BinOp ! type Exp = record case arity : intof 0 : (val : int ); 1 : (op : int, opnd : ExpP ) 2 : (op : int, opnd1, opnd2 : ExpP ) end We can now write, e.g., if p ^. arity = 1 then p := p ^ . opnd …. arity: op/val: opnd/opnd1: opnd2: Essence of OOP

More Related