Skip to content

Commit 6e22967

Browse files
authored
Merge pull request #4930 from luishendrix92/main
#29 - OCaml
2 parents 1733fa3 + e19a9c5 commit 6e22967

File tree

1 file changed

+195
-0
lines changed

1 file changed

+195
-0
lines changed
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
(******************************************************************************)
2+
(* *)
3+
(* Interface Segregation Principle *)
4+
(* *)
5+
(* The core concept of this principle (the 'I' in {b SOLID}) is, a class *)
6+
(* should not be forced to implement methods that it doesn't need, caused *)
7+
(* by the implementation of a broad interface, or inheriting from a general *)
8+
(* abstract class that covers more ground than it should. *)
9+
(* *)
10+
(* The proposed solution is to create smaller interfaces that are only im- *)
11+
(* plemented if the class needs those methods and/or members and only *)
12+
(* inherit from a base class that won't force unwanted implementations. It *)
13+
(* goes hand in hand with the Liskov-Substitution Principle as it helps *)
14+
(* reduce the amount of exceptions thrown. *)
15+
(* *)
16+
(******************************************************************************)
17+
18+
open Printf
19+
20+
(* This interface violates the ISP because if implemented by a specific type of
21+
coffee machine, it will be forced to implement methods that it doesn't need
22+
and thus it'll need to either throw an exception or provide a NoOP body. *)
23+
class type coffee_machine_violating_isp = object
24+
method drip_brew : unit
25+
method replace_filter : unit
26+
method steam_milk : unit
27+
method pressure_brew : unit
28+
method add_ground_coffee : unit
29+
end
30+
31+
class type coffee_machine = object
32+
method brew : unit
33+
method add_ground_coffee : unit
34+
end
35+
36+
class type drip = object
37+
(* Inheriting a class type from another class type in OCaml is the same
38+
as extending an interface in OOP languages. Though we can't implement
39+
multiple interfaces, we can in fact inherit from multiple classes! *)
40+
inherit coffee_machine
41+
method drip_brew : unit
42+
method replace_filter : unit
43+
end
44+
45+
class type espresso = object
46+
inherit coffee_machine
47+
method steam_milk : unit
48+
method pressure_brew : unit
49+
end
50+
51+
class drip_machine : drip =
52+
object (self)
53+
method private drip_brew = print_endline "Brewing through a paper filter..."
54+
55+
method add_ground_coffee =
56+
print_endline "Adding ground coffee to drip coffee machine..."
57+
58+
method replace_filter = print_endline "Replacing paper filter..."
59+
method brew = self#drip_brew
60+
end
61+
62+
class espresso_machine : espresso =
63+
object (self)
64+
method private pressure_brew =
65+
print_endline "Brewing through an espresso portafilter..."
66+
67+
method add_ground_coffee =
68+
print_endline
69+
"Adding and compressing ground coffee to espresso machine..."
70+
71+
method steam_milk = print_endline "Steaming milk for latte art..."
72+
method brew = self#pressure_brew
73+
end
74+
75+
let _ =
76+
let oster_drip : drip_machine = new drip_machine in
77+
let barista : espresso_machine = new espresso_machine in
78+
oster_drip#add_ground_coffee;
79+
oster_drip#brew;
80+
oster_drip#replace_filter;
81+
barista#add_ground_coffee;
82+
barista#brew;
83+
barista#steam_milk
84+
;;
85+
86+
(******************************************************************************)
87+
(* *)
88+
(* Dificultad Extra (Opcional) *)
89+
(* *)
90+
(* Crea un gestor de impresoras. *)
91+
(* Requisitos: *)
92+
(* 1. Algunas impresoras solo imprimen en blanco y negro. *)
93+
(* 2. Otras solo a color. *)
94+
(* 3. Otras son multifunción, pueden imprimir, escanear y enviar fax. *)
95+
(* Instrucciones: *)
96+
(* 1. Implementan el sistema, con los diferentes tipos de impresoras y fun- *)
97+
(* ciones. *)
98+
(* 2. Aplica el ISP a la implementación. *)
99+
(* 3. Desarrolla un código que compruebe que se cumple el principio. *)
100+
(* *)
101+
(******************************************************************************)
102+
103+
class virtual black_white_printing =
104+
object
105+
method virtual print_b_and_w : string -> unit
106+
end
107+
108+
class virtual color_printing =
109+
object
110+
method virtual print_color : string -> unit
111+
end
112+
113+
class virtual fax (number : string) =
114+
object
115+
val phone_number = number
116+
method virtual send_document : string -> string -> unit
117+
end
118+
119+
class virtual scanner =
120+
object
121+
method virtual scan_document : string -> unit
122+
end
123+
124+
class bw_printer =
125+
object
126+
inherit black_white_printing
127+
128+
method print_b_and_w docfile =
129+
printf "Printing [%s] in black and white...\n" docfile
130+
end
131+
132+
class color_printer =
133+
object
134+
inherit color_printing
135+
136+
method print_color docfile =
137+
printf "Printing [%s] in CYMK color...\n" docfile
138+
end
139+
140+
class multifunctional_printer (number : string) =
141+
object (self)
142+
(* As I mentioned before, OCaml's class system offers multiple inheritance
143+
but I could have also made them interfaces (class types) and in order to
144+
create an interface that 'implements' all of them we could have done:
145+
146+
{[
147+
class multifunctional_printer (number : string) : object
148+
inherit color_printing
149+
inherit black_white_printing
150+
inherit scanner
151+
inherit fax
152+
end = object (self) end
153+
]}
154+
155+
This way we'd be forced to implement all of those methods but with one
156+
catch: using class types 'seals' a class, meaning we can't expose more
157+
public methods other than the ones in the interface.
158+
*)
159+
inherit color_printing
160+
inherit black_white_printing
161+
inherit scanner
162+
inherit fax number
163+
164+
method scan_document docfile =
165+
printf "Scanning [%s] with a multifunctional\n" docfile
166+
167+
method send_document docfile destination_number =
168+
printf
169+
"Sending [%s] from #%s to fax #%s through a multifunctional\n"
170+
docfile
171+
phone_number
172+
destination_number
173+
174+
method private print_b_and_w docfile =
175+
printf
176+
"Printing [%s] in black and white using a multifunctional\n"
177+
docfile
178+
179+
method private print_color docfile =
180+
printf "Printing [%s] in CYMK color using a multifunctional\n" docfile
181+
182+
method print ?(use_color = true) docfile =
183+
if use_color then self#print_color docfile else self#print_b_and_w docfile
184+
end
185+
186+
let _ =
187+
let compaq_bw = new bw_printer in
188+
let epson_color = new color_printer in
189+
let epson_mf = new multifunctional_printer "664-934-1295" in
190+
compaq_bw#print_b_and_w "2024report.xlsx";
191+
epson_color#print_color "wedding_album.pdf";
192+
epson_mf#print ~use_color:false "essat.docx";
193+
epson_mf#send_document "private_letter.txt" "55-676-2424";
194+
epson_mf#scan_document "ocr_test.jpg"
195+
;;

0 commit comments

Comments
 (0)