CS代考 Problem with Id class (contd)

Problem with Id class (contd)

OO-approach more strongly typed than ParseTree class approach
But type errors still possible

Copyright By PowCoder代写 加微信 powcoder

::= | + | *
class Exp {
private: int kind; int i; Exp* e1; Exp* e2;
int evalExp() {
if (kind==1) return(i);
if (kind==2) return( e1->evalExp() + e2->evalExp() );
if (kind==3) return( e1->evalExp() * e2->evalExp() ); }
Types, Polymorphism
Knowledge check:
Knowledge check:
What “type” errors are possible here?
Knowledge check:
Cannot be solved this by having muliiple classes,
IntExp, SumExp, ProdExp …Why not?

Three types of polymorphism:
Universal (generics), Subtype, Ad-hoc
Universal: Haskell does the best job of this
In fact, Haskell even handles Ad-hoc polymorphism cleanly
For our current type problem, we will use Subtype polymorphism
Ad-hoc: example.: +, * for int, float, etc.
Polymorphism

Solution: Subtype polymorphism:
Three classes for the three different types of Exp
but also include a base class, Exp
class Exp {
virtual int evalExp() = 0; // “abstract” in Java:
bool isEven() { // *not* virtual
int k = evalExp(); // on which object?
// Every method of a class has an implicit parameter
return ((k%2) == 0) ; } };

Knowledge check:
Passed by reference? Copy?
Knowledge check: Does every method
really have such a parameter?
Knowledge check (contd):
What about static methods?
Knowledge check::
Cannot construct objects of type Exp; why not?

class intExp : public Exp { // integer expression
private: int i;
public: intExp( int j) { i = j; }
int evalExp() { return i; } };
class sumExp : public Exp { // sum expression
private: Exp* e1; Exp* e2;
sumExp( Exp* e, Exp* f) { e1 = e; e2 = f; }
int evalExp() { return(e1->evalExp() + e2->evalExp()); } };
class prodExp : public Exp { // product expression
private: Exp* e1; Exp* e2;
// … similar to sumExp; replace “+” by “*” }

Knowledge check: But we just saw we cannot
construct objects of type Exp! What is going on?

Each object, whether it is of type intExp or sumExp or prodExp, has an extra word of memory that contains the address of the particular evalExp() that applies to objects of that particular type
The runtime system, when it constructs an object of that type, allocates an extra word of memory to hold that address
And it puts the address of that particular evalExp() in that word of memory

When evalExp() is on an object of one of these types is executed at run-time, the r.t. system “dispatches” the call to the address in that extra word which is, usually, at the start of the object

How Does it Work?
Knowledge check:
When exactly is this?
Knowledge check: How does the run-time system know what this address is?

Exp* expArray[6];

expArray[0] = new intExp(5);
expArray[1] = new intExp(10);

expArray[2] = new sumExp(expArray[0],expArray[1]);
expArray[3] = new prodExp(expArray[0],expArray[1]);
expArray[4] = new sumExp(expArray[2],expArray[3]);
expArray[5] = new prodExp(expArray[2],expArray[3]);

for (i=0; i<6; i++) { print(expArray[i] ->evalExp()); }

Knowledge check:
What will expArray[0],[1] look like?
Knowledge check:
What will expArray[2],[3] look like?
Knowledge check:
What will expArray[4],[5] look like?
Knowledge check:
What will happen if there is more than one virtual method?

We can define a new derived class of Exp
Instances of that new derived class can be made up of instances of existing classes
Once we define evalExp() in the new derived class, at run-time, it will, very likely invoke the evalExp() in the existing derived classes and it will work seamlessly with no changes in the existing code!
class condExp: public Exp { // as in C
private: boolExp* b; Exp* e1; Exp* e2;
condExp( boolExp* bb; Exp* ee1; Exp* ee2;
{ b = bb; e1 = ee1; e2 = ee2; }
int evalExp() {
return ( eval(bb) ? e1->evalExp() : e2->evalExp() );}

And That’s Not All!
Knowledge check:
Why does the evaluation of bb use a different syntax than the ones for e1, e2?
Knowledge check:
Would it be possible to make boolExp a derived class of Exp so we can use the same syntax?

In Java and C++, the compiler ensures that there are no type errors in the code even in the presence of polymorphism
This is not possible in a language such as Python.
In Python, type-checking has to be done at runtime
Python type-checking is also called “duck typing”
(There are also other terms you will come across such as “static” vs. “dynamic” typing, etc.)

Type-checking: Compile-time vs Runtime
Knowledge check: Why?
Why not at compile-time?

Consider the following:
Define an abstract base class Node with three
virtual methods, Parse(), Print(), Execute()
In each of our current classes such as SS, Stmt, If, etc., replace declarations such as Stmt* st, SS* ss1, etc., by Node* st, Node* ss1, etc.
Will this work?
Assuming that it will work, is it a good idea?

Knowledge Check: Is it Possible to Go Too Far?

/docProps/thumbnail.jpeg

程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com