![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
As sather is an object oriented language, classes play an important role in the language.
The class system of Sather is somehow complicated. It contains partial classes, abstracted classes, parametrized classes, and immutable classes as well as conventional ones. I am explaining about conventional and abstracted classes in this section, then I will explain about parametrized and immutable classes in section 7 and 8.
Let's think about cellphones. A cellphones is a mailer as well as a telephone. Thus cellphones inherit the function of telephone and mailer. Sather supports multiple inheritance and the telephone, the mailer, and the cellphone classes can be defined like as follows.
01: class PHONE is -- The telephone class 02: 03: private attr phone_number:STR; -- the phone number. Keywords private and attr mean that the parameter is private and belonging to instance, respectively 04: -- if not private keyword, it is public 05: 06: create(pn:STR):SAME is -- create is the constructor in C++ 07: return new.init(pn); -- new allocate memory and apply init to it 08: end; -- The SAME is the class that calls create. SAME should be used as the class can be inherited. 09: 10: private init(pn:STR):SAME is -- init is a function to initialize. Even there are several way to implement create, 11: phone_number := pn; -- return new.init suit inheritance. The function initialize the instance parameter, phone_number. 12: return self; -- returning the initialized instance (self). 13: end; 14: 15: get_number:STR is -- The method to get the phone number. The self in the self.phone_number can be omitted. 16: return phone_number; 17: end; 18: 19: phone_call(to:SAME, msg:STR):STR is -- The method to call. The argument is other phone and message. 20: return "From: " + phone_number + -- It just returns a string (to make it simple). 21: "\nTo: " + to.phone_number + -- You can specify the instance like to.phone_number. 22: "\nSubject: " + msg + "\n"; -- This method also use SAME. Use SAME as many as possible. 23: end; 24: end; -- end of PHONENotes:
phone1:PHONE:=PHONE::create("012-345-6789"); -- Formal way. Use this if the compiler doesn't like the abbreviations. phone2:PHONE:=#PHONE("023-444-5555"); -- '#PHONE' is the abbreviation of PHONE::create phone3:PHONE:=#("023-4545-6767"); -- You can omit the class name in many cases.
01: class MAIL is 02: private attr address:STR; -- mail address 03: private attr newmails:LIST{STR}; -- the list of new mail, whose type is LIST{STR} 04: private shared mailinglist:LIST{STR}:=LIST{STR}::create; -- declaring and defining a class parameter mailinglist whose type is LIST{STR}. 05: -- In the case of constant and shared, you cannot use the abbreviation with '#'. 06: create(ad:STR):SAME is 07: return new.init(ad); 08: end; 09: 10: init(ad:STR):SAME is 11: newmails := #LIST{STR}; -- Making the list of new mail. 12: address := ad; -- Setting its own address 13: return self; -- returning itself 14: end; 15: 16: get_address:STR is -- getting the address 17: return address; 18: end; 19: 20: send(to:SAME, msg:STR) is -- The mail sending method, which add the message on his list of new mails. 21: to.newmails.append("From: " + address + "\nSubject: " + msg + "\n"); 22: end; 23: 24: send2mailinglist(msg:STR) is -- Submitting to the mailing list. it add the message to the list. 25: mailinglist.append("From: " + address + "\nSubject: " + msg + "\n"); 26: end; 27: 28: read_mail:STR is -- Reading mails 29: s:STR := address + " received following new messages:\n"; 30: loop 31: s := s+ newmails.elt!; -- Taking a new mali from the new-mail-list. 32: end; 33: newmails.clear; -- Clearing the new-mail-list 34: return s + "\n"; 35: end; 36: 37: read_mailinglist:STR is -- Reading the mailing list. 38: s:STR := "Messages in the mailing list are:\n"; 39: loop 40: s := s+ mailinglist.elt!; 41: end; 42: return s + "\n"; 43: end; 44: 45: end; -- end of MAILесет
01: class MOBILE is 02: include PHONE init -> phone_init, create ->; -- include indicates inhelitance 03: include MAIL init -> mail_init, create ->; -- Renaming the MAIL's init to mail_init and forgetting MAIL's create. 04: 05: create(ph,ad:STR):SAME is 06: return new.phone_init(ph).mail_init(ad); -- Concise code using parents init methods. 07: end; 08: 09: end; -- end of MOBILE
01: class MAIN is 02: 03: main(av: ARRAY{STR}) is 04: if av.size = 5 then 05: mob1:MOBILE := #(av[1], av[2]); -- Making two cellphones 06: mob2:MOBILE := #(av[3], av[4]); 07: mobile_test(mob1, mob2); -- and test them. 08: else 09: #ERR + "Usage:mobile PHONE_NUMBER_1 EMAIL_ADDRESS_1 PHONE_NUMBER_2 EMAIL_ADDRES_2 \n"; 10: end; 11: end; 12: 13: mobile_test(mob1, mob2:MOBILE) is 14: #OUT + "Phone number(1) is " + mob1.get_number + "\n"; -- Showing the phone number of cellphone one. 15: #OUT + "E-mail address(1) is " + mob1.get_address + "\n"; -- Showing the mail address of cellphone one. 16: #OUT + "\nPhone call test (1) -> (2):\n" + -- Calling from cellphone one to cellphone two. 17: mob1.phone_call(mob2, "Hello"); 18: #OUT + "\nE-mail transfer test (2) -> (1):\n"; 19: mob2.send(mob1, "How are you?"); -- Sending an email message to cellphone two to cellphone one. 20: mob2.send(mob1, "I want to see you."); -- Sending an email message to cellphone two to cellphone one again. 21: #OUT + mob1.read_mail; -- Cellphone one check the new mails. 22: #OUT + "\nTest for mailing list:\n"; 23: mob1.send2mailinglist("Is Sather good?"); -- Cellphone one submit a message to the mailing list. 24: mob2.send2mailinglist("Yes. Sather is good."); -- Cellphone two also submit a message to the mailing list. 25: #OUT + mob1.read_mailinglist + "\n"; -- Checking the mailing list 26: end; 27: end; -- end of MAIN 28:
> sacomp mobile.sa -o mobile > ./mobile 012-222-3333 foo@ab.ne.jp 023-444-5677 bar@cd.com Phone number(1) is 012-222-3333 E-mail address(1) is foo@ab.ne.jp Phone call test (1) -> (2): From: 012-222-3333 To: 023-444-5677 Subject: Hello E-mail transfer test (2) -> (1): foo@ab.ne.jp received following new messages: From: bar@cd.com Subject: How are you? From: bar@cd.com Subject: I want to see you. Test for mailing list: Messages in the mailing list are: From: foo@ab.ne.jp Subject: Is Sather good? From: bar@cd.com Subject: Yes. Sather is good.
Let's think abou a wireless LAN (WLAN). As the WLAN has a risk of tapping, the trafic should be encoded by using a encryption technology such as WEP and WPA.
Following code defines a partial class WLAN and two children WEP and WPA_PSK.
01: -- an example of partical classes, WLAN 02: 03: partial class WLAN is 04: 05: stub security:STR; -- This attribure should be defined in the children classes. 06: 07: get_security:STR is 08: return security; -- getting the attribute named security. 09: end; 10: 11: end; -- WLAN 12: 13: 14: class WEP is 15: include WLAN; 16: 17: const security:STR := "wep"; 18: private attr key:STR; 19: 20: create(k:STR):SAME is 21: return new.init(k); 22: end; 23: 24: init(k:STR):SAME is 25: key := k; 26: return self; 27: end; 28: 29: get_key:STR is 30: return key; 31: end; 32: 33: end; -- WEP 34: 35: class WPA_PSK is 36: include WLAN; 37: 38: const security:STR := "wpa psk"; 39: private attr key:STR; 40: 41: create(k:STR):SAME is 42: return new.init(k); 43: end; 44: 45: init(k:STR):SAME is 46: key := k; 47: return self; 48: end; 49: 50: get_key:STR is 51: return key; 52: end; 53: 54: end; -- WPA_PSK 55: 56: 57: 58: class MAIN is 59: 60: main is 61: wlan_test; 62: end; 63: 64: wlan_test is 65: wep0:WEP:=#("foo"); 66: wpa0:WPA_PSK:=#("bar"); 67: 68: #OUT + "Security and key of wep0 are: " + wep0.get_security + " and \"" + wep0.get_key + "\".\n"; 69: #OUT + "Security and key of wpa0 are: " + wpa0.get_security + " and \"" + wpa0.get_key + "\".\n"; 70: 71: end; 72: end; -- end of MAINFollowing shows the output.
$ sacomp wlan.sa -o wlan $ ./wlan Security and key of wep0 are: wep and "foo". Security and key of wpa0 are: wpa psk and "bar".
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |