<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Tomas<div class=""><br class=""></div><div class="">In your code you had the following question:<div class=""><div class=""> PROCEDURE Write(t: Term.Term; ch: CHAR);<br class=""><blockquote type="cite" class=""></blockquote> BEGIN<br class=""><blockquote type="cite" class=""></blockquote> ch := CAP(ch); Texts.Write(W, ch); Texts.Append(Oberon.Log, W.buf)<br class=""><blockquote type="cite" class=""></blockquote><font color="#ff2600" class=""> (* could we call base Write instead of Texts.Write/Append ? *)<br class=""></font> END Write;<div><br class=""></div><div>Yes, you can. You could e.g. modify three lines of your CapTerm as follows:</div><div><br class=""></div><div>Instead of </div><div>(*1*) VAR W: Texts.Writer; m: Term.Methods;</div><div>(*2*) PROCEDURE Init*(t: CapTerm; color: INTEGER (* other data for the</div><div> CapTerm if any *) ); BEGIN t.do := m; t.col := color END Init;</div><div>(*3*) BEGIN Texts.OpenWriter(W); NEW(m); Term.InitMethods(m); m.Write := Write</div><div><br class=""></div><div>You write</div><div><div><div>(*1*) VAR W: Texts.Writer; <font color="#ff2600" class="">self, super</font>: Term.Methods;</div><div>(*2*) PROCEDURE Init*(t: CapTerm; color: INTEGER (* other data for the</div><div> CapTerm if any *) ); BEGIN t.do := <font color="#ff2600" class="">self</font>; t.col := color END Init;</div><div>(*3*) BEGIN Texts.OpenWriter(W); NEW(<font color="#ff2600" class="">super</font>); Term.InitMethods(<font color="#ff2600" class="">super</font>); <font color="#ff2600" class="">NEW(self); self^:= super^; self.</font>Write := Write</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">After these three modifications your CapTerm.Write could look like this:</div><div class=""> PROCEDURE Write(t: Term.Term; ch: CHAR);<br class=""><blockquote type="cite" class=""></blockquote> BEGIN<br class=""><blockquote type="cite" class=""></blockquote> ch := CAP(ch); super.Write(t, ch)<br class=""> END Write;</div><div class=""><br class=""></div><div class=""><br class=""></div></div><div class="">br</div></div><div>Jörg<br class=""><blockquote type="cite" class=""><div class="">Am 15.08.2018 um 14:34 schrieb Tomas Kral <<a href="mailto:thomas.kral@email.cz" class="">thomas.kral@email.cz</a>>:</div><br class="Apple-interchange-newline"><div class=""><div class="">Hi,<br class=""><br class="">I have recoded the example as advised.<br class=""><br class=""><blockquote type="cite" class="">1) Space.<br class=""></blockquote><br class="">Every Term based type (class) carries its own copy of methods, some may<br class="">be [overriden] overwritten, e.g. Write.<br class=""><br class="">NEW(m); m^ = methods^; m.Write := Write<br class=""><br class=""><blockquote type="cite" class="">2) Consistency.<br class=""></blockquote><br class="">To keep the same methods for all Term based types, we can leave out<br class="">NEW(m), and just assign a pointer.<br class=""><br class="">(*NEW(m)*); m = methods;<br class=""><br class="">QUESTION, can we somehow call base method from the overwritten one?<br class=""><br class="">(* ------- OOP EXAMPLE -------- *)<br class=""><br class="">MODULE Term; (* TK 15.8.2018 revised OOP example *)<br class=""> IMPORT Texts, Oberon;<br class=""><br class=""> TYPE<br class=""> Term* = POINTER TO TDesc;<br class=""> Methods* = POINTER TO MDesc;<br class=""><br class=""> (* Base method suite *)<br class=""> MDesc* = RECORD<br class=""> Write*: PROCEDURE(t: Term; ch: CHAR);<br class=""> Refresh*: PROCEDURE(t: Term)<br class=""> (* other methods come here *)<br class=""> END ;<br class=""><br class=""> (* Base data suite *)<br class=""> TDesc* = RECORD<br class=""> do*: Methods;<br class=""> (* generic terminal data comes here *)<br class=""> END ;<br class=""><br class=""> VAR W: Texts.Writer; methods: Methods;<br class=""><br class=""> (* ------ Initialisation for clients ------ *)<br class=""><br class=""> PROCEDURE Init*(t: Term);<br class=""> BEGIN t.do := methods<br class=""> END Init;<br class=""><br class=""> PROCEDURE InitMethods*(VAR m: Methods);<br class=""> BEGIN m^ := methods^<br class=""> END InitMethods;<br class=""><br class=""> (* ------ Term base methods ----- *)<br class=""><br class=""> PROCEDURE Write(t: Term; ch: CHAR);<br class=""> BEGIN Texts.Write(W, ch)<br class=""> END Write;<br class=""><br class=""> PROCEDURE Refresh(t: Term);<br class=""> BEGIN Texts.Append(Oberon.Log, W.buf)<br class=""> END Refresh;<br class=""><br class="">BEGIN Texts.OpenWriter(W); NEW(methods); methods.Write := Write;<br class=""> methods.Refresh := Refresh END Term.<br class=""><br class=""><br class="">MODULE CapTerm;<br class=""> IMPORT Texts, Oberon, Term;<br class=""><br class=""> TYPE<br class=""> CapTerm* = POINTER TO CTDesc;<br class=""> CTDesc* = RECORD (Term.TDesc)<br class=""> (* specific cap terminal data comes here *)<br class=""> col: INTEGER <br class=""> END ;<br class=""><br class=""> VAR W: Texts.Writer; m: Term.Methods;<br class=""><br class=""> PROCEDURE Init*(t: CapTerm; color: INTEGER (* other data for the<br class=""> CapTerm if any *) ); BEGIN t.do := m; t.col := color<br class=""> END Init;<br class=""><br class=""> PROCEDURE CAP*(ch: CHAR): CHAR;<br class=""> VAR up: CHAR;<br class=""> BEGIN<br class=""> IF (ch >= "a") OR (ch <= "z") THEN<br class=""> up := CHR(ORD(ch) + ORD("A") - ORD("a"))<br class=""> ELSE up := ch END<br class=""> RETURN up END CAP;<br class=""><br class=""> (* --------- Methods to override from Term base ------- *)<br class=""><br class=""> PROCEDURE Write(t: Term.Term; ch: CHAR);<br class=""> (* Write method specific for CapTerm *)<br class=""> BEGIN<br class=""> ch := CAP(ch); Texts.Write(W, ch); Texts.Append(Oberon.Log, W.buf)<br class=""> (* could we call base Write instead of Texts.Write/Append ? *)<br class=""> END Write;<br class=""><br class=""> (* Refresh() method not to be overriden *)<br class=""><br class="">BEGIN Texts.OpenWriter(W); NEW(m); Term.InitMethods(m); m.Write := Write<br class="">END CapTerm.<br class=""><br class=""><br class="">MODULE TestTerm;<br class=""> IMPORT Texts, Oberon, Term, CapTerm;<br class=""><br class=""> VAR<br class=""> W: Texts.Writer; t: Term.Term; c: CapTerm.CapTerm;<br class=""><br class=""> PROCEDURE Run*;<br class=""> VAR S: Texts.Scanner;<br class=""> BEGIN<br class=""> Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);<br class=""> Texts.Scan(S); WHILE S.class = Texts.Name DO<br class=""> t.do.Write(t, S.s[0]); t.do.Refresh(t); <br class=""> c.do.Write(c, S.s[0]); c.do.Refresh(c); (* calls Term.Refresh() *)<br class=""> Texts.Scan(S)<br class=""> END ;<br class=""> Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf)<br class=""> END Run;<br class=""><br class="">BEGIN Texts.OpenWriter(W);<br class=""> NEW(t); Term.Init(t);<br class=""> NEW(c); CapTerm.Init(c, 20)<br class="">END TestTerm.<br class=""><br class="">TestTerm.Run a b c ~<br class=""><br class=""><br class="">-- <br class="">Tomas Kral <<a href="mailto:thomas.kral@email.cz" class="">thomas.kral@email.cz</a>><br class="">--<br class=""><a href="mailto:Oberon@lists.inf.ethz.ch" class="">Oberon@lists.inf.ethz.ch</a> mailing list for ETH Oberon and related systems<br class=""><a href="https://lists.inf.ethz.ch/mailman/listinfo/oberon" class="">https://lists.inf.ethz.ch/mailman/listinfo/oberon</a><br class=""></div></div></blockquote></div><br class=""></div></div></div></body></html>