Details on Using Classes
Details on Using Classes
Returning an Object from a Function
Introduction
A function can be made to return an object of a class type (in the body of the function, you can declare any variable(s) you want). Of course, you must know the class of the object you want to return. You can use an existing/built-in class or you can create your own. When defining the function, make sure its last statement indicates an object. Outside the function, you can call it, get its return value, and use it as you see fit, such as displaying the values of its properties and calling its methods. Here is an example where the last line of the function specifies that it is returning a variable that was declared locally:
type Employee() = let mutable emplNbr = "" let mutable fn = "" let mutable ln = "" let mutable sal = 0.00 member this.EmployeeNumber with get() = emplNbr and set(value) = emplNbr <- value member this.FirstName with get() = fn and set(value) = fn <- value member this.LastName with get() = ln and set(value) = ln <- value member this.HourlySalary with get() = sal and set(value) = sal <- value let createEmployeeRecord() = let empl : Employee = Employee() empl.EmployeeNumber <- "2080-4813" empl.FirstName <- "James" empl.LastName <- "Alexanders" empl.HourlySalary <- 22.25 empl let empl = createEmployeeRecord() printfn "Employee Payroll Summary" printfn "----------------------------------------------------" printfn "Employee #: %s" empl.EmployeeNumber printfn "Full Name: %s %s" empl.FirstName empl.LastName printfn "Hourly Salary: %0.02F" empl.HourlySalary printfn "----------------------------------------------------"
This would produce:
Employee Payroll Summary ---------------------------------------------------- Employee #: 2080-4813 Full Name: James Alexanders Hourly Salary: 22.25 ---------------------------------------------------- Press any key to continue . . .
Returning a New Object
Instead of declaring a local variable, if the class has one or more constructors, you can use it/them in the last line and pass the desired or appropriate arguments to indicate the return value. Here is an example:
type Employee(emplNbr, fname, lname, salary) = member val EmployeeNumber = emplNbr with get, set member val FirstName = fname with get, set member val LastName = lname with get, set member val HourlySalary = salary with get, set let createEmployeeRecord() = let emplNbr = "2080-4813" let fn = "James" let ln = "Alexanders" let sal = 22.25 new Employee(emplNbr, fn, ln, sal) let empl = createEmployeeRecord() printfn "Employee Payroll Summary" printfn "----------------------------------------------------" printfn "Employee #: %s" empl.EmployeeNumber printfn "Full Name: %s %s" empl.FirstName empl.LastName printfn "Hourly Salary: %0.02F" empl.HourlySalary printfn "----------------------------------------------------"
Although F# is an inferred language, if you want to indicate the return type of a function, type : and the type before the = symbol. Here is example:
type Employee(emplNbr, fname, lname, salary) =
member val EmployeeNumber = emplNbr with get, set
member val FirstName = fname with get, set
member val LastName = lname with get, set
member val HourlySalary = salary with get, set
let createEmployeeRecord() : Employee =
let emplNbr = "2080-4813"
let fn = "James"
let ln = "Alexanders"
let sal = 22.25
new Employee(emplNbr, fn, ln, sal)
let empl = createEmployeeRecord()
printfn "Employee Payroll Summary"
printfn "----------------------------------------------------"
printfn "Employee #: %s" empl.EmployeeNumber
printfn "Full Name: %s %s" empl.FirstName empl.LastName
printfn "Hourly Salary: %0.02F" empl.HourlySalary
printfn "----------------------------------------------------"
You can also pass additional parameters, such as those of primitive types, to the function and use them in the body of the function as you see fit. Here is an example:
type Employee(emplNbr, fname, lname, salary) =
member val EmployeeNumber = emplNbr with get, set
member val FirstName = fname with get, set
member val LastName = lname with get, set
member val HourlySalary = salary with get, set
let createEmployeeRecord nbr first last salary : Employee =
new Employee(nbr, first, last, salary)
let empl = createEmployeeRecord "2080-4813" "James" "Alexanders" 22.25
printfn "Employee Payroll Summary"
printfn "----------------------------------------------------"
printfn "Employee #: %s" empl.EmployeeNumber
printfn "Full Name: %s %s" empl.FirstName empl.LastName
printfn "Hourly Salary: %0.02F" empl.HourlySalary
printfn "----------------------------------------------------"
An Object as Parameter
A function can be defined to take an object as parameter. In this case, when creating the function, you should specify the data type of the parameter. In the body of the function, use the parameter as you see fit. Here is an example:
type Employee(emplNbr, fname, lname, salary) =
let mutable nbr = emplNbr
let mutable fn = fname
let mutable ln = lname
let mutable sal = salary
member this.EmployeeNumber with get() = nbr and set(value) = nbr <- value
member this.FirstName with get() = fn and set(value) = fn <- value
member this.LastName with get() = ln and set(value) = ln <- value
member this.HourlySalary with get() = sal and set(value) = sal <- value
let createEmployeeRecord() : Employee =
Employee("2080-4813", "James", "Alexanders", 22.25)
let present (empl : Employee) =
printfn "Employee Payroll Summary"
printfn "----------------------------------------------------"
printfn "Employee #: %s" empl.EmployeeNumber
printfn "Full Name: %s %s" empl.FirstName empl.LastName
printfn "Hourly Salary: %0.02F" empl.HourlySalary
printfn "----------------------------------------------------"
let empl = createEmployeeRecord()
present empl
Besides the object from class, you can pass other parameters. Some can be based on primitive types. Here is an example:
type Employee(emplNbr, fname, lname, salary) =
let mutable nbr = emplNbr
let mutable fn = fname
let mutable ln = lname
let mutable sal = salary
member this.EmployeeNumber with get() = nbr and set(value) = nbr <- value
member this.FirstName with get() = fn and set(value) = fn <- value
member this.LastName with get() = ln and set(value) = ln <- value
member this.HourlySalary with get() = sal and set(value) = sal <- value
let createEmployeeRecord() : Employee =
Employee("2080-4813", "James", "Alexanders", 22.25)
let present (empl : Employee) mon tue wed thu fri =
printfn "Employee Payroll Summary"
printfn "----------------------------------------------------"
printfn "Employee #: %s" empl.EmployeeNumber
printfn "Full Name: %s %s" empl.FirstName empl.LastName
printfn "Hourly Salary: %0.02F" empl.HourlySalary
printfn "----------------------------------------------------"
printfn "Pay Summary - Time Worked"
printfn "Monday: %0.02f" mon
printfn "Tuesday: %0.02f" tue
printfn "Wednesday: %0.02f" wed
printfn "Thursday: %0.02f" thu
printfn "Friday: %0.02f" fri
let empl = createEmployeeRecord()
present empl 8.50 9.00 7.50 8.00 8.00
This would produce:
Employee Payroll Summary ---------------------------------------------------- Employee #: 2080-4813 Full Name: James Alexanders Hourly Salary: 22.25 ---------------------------------------------------- Pay Summary - Time Worked Monday: 8.50 Tuesday: 9.00 Wednesday: 7.50 Thursday: 8.00 Friday: 8.00 Press any key to continue . . .
You can also pass more than one object as parameter. The parameters can be of the same type or different types. Here is an example:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, fname, lname, status, salary) =
member val EmployeeNumber = emplNbr with get, set
member val FirstName = fname with get, set
member val LastName = lname with get, set
member val Status = status with get, set
member val HourlySalary = salary with get, set
member this.Present() : unit =
printfn "Employee Payroll Summary"
printfn "----------------------------------------------------"
printfn "Employee #: %s" this.EmployeeNumber
printfn "Full Name: %s %s" this.FirstName this.LastName
printfn "Status: %A" this.Status
printfn "Hourly Salary: %0.02F" this.HourlySalary
printfn "----------------------------------------------------"
type Payroll() =
let mutable emplNbr = ""
let mutable mon = 0.00
let mutable tue = 0.00
let mutable wed = 0.00
let mutable thu = 0.00
let mutable fri = 0.00
member this.EmployeeNumber with get() = emplNbr and set(value) = emplNbr <- value
member this.Monday with get() = mon and set(value) = mon <- value
member this.Tuesday with get() = tue and set(value) = tue <- value
member this.Wednesday with get() = wed and set(value) = wed <- value
member this.Thursday with get() = thu and set(value) = thu <- value
member this.Friday with get() = fri and set(value) = fri <- value
let validate (empl : Employee) (pay : Payroll) : bool =
if empl.EmployeeNumber = pay.EmployeeNumber then
true
else
false
let staff = Employee("7092-3094", "Rose", "Crittenden", EmploymentStatus.FullTime, 24.05)
let pay = Payroll()
pay.EmployeeNumber <- "2080-4813"
pay.Monday <- 22.25
pay.Tuesday <- 8.50
pay.Wednesday <- 9.50
pay.Thursday <- 8.00
pay.Friday <- 10.00
if validate staff pay = true then
printfn "The payroll will be calculated"
else
printfn "The information you provided for the employee and the payroll do not match"
You can also pass a combination of parameters of class types and primitive types. Here is an example:
type EmploymentStatus =
| Unknown = 0
| FullTime = 1
| PartTime = 2
| Intern = 3
| Seasonal = 4
type Employee(emplNbr, fname, lname, status, salary) =
member val EmployeeNumber = emplNbr with get, set
member val FirstName = fname with get, set
member val LastName = lname with get, set
member val Status = status with get, set
member val HourlySalary = salary with get, set
member this.Present() : unit =
printfn "Employee Payroll Summary"
printfn "----------------------------------------------------"
printfn "Employee #: %s" this.EmployeeNumber
printfn "Full Name: %s %s" this.FirstName this.LastName
printfn "Status: %A" this.Status
printfn "Hourly Salary: %0.02F" this.HourlySalary
printfn "----------------------------------------------------"
type Payroll() =
let mutable emplNbr = ""
let mutable mon = 0.00
let mutable tue = 0.00
let mutable wed = 0.00
let mutable thu = 0.00
let mutable fri = 0.00
member this.EmployeeNumber with get() = emplNbr and set(value) = emplNbr <- value
member this.Monday with get() = mon and set(value) = mon <- value
member this.Tuesday with get() = tue and set(value) = tue <- value
member this.Wednesday with get() = wed and set(value) = wed <- value
member this.Thursday with get() = thu and set(value) = thu <- value
member this.Friday with get() = fri and set(value) = fri <- value
let validate (empl : Employee) (pay : Payroll) salaryIsFixed : float =
let mutable result = 0.00
if empl.EmployeeNumber = pay.EmployeeNumber then
if salaryIsFixed = true then
result <- empl.HourlySalary * 40.00
else
result <- empl.HourlySalary * (pay.Monday + pay.Tuesday + pay.Wednesday + pay.Thursday + pay.Friday)
else
printfn "The information you provided for the employee and the payroll do not match"
result
let staff = Employee("7092-3094", "Rose", "Crittenden", EmploymentStatus.FullTime, 24.05)
let pay = Payroll()
pay.EmployeeNumber <- "7092-3094"
pay.Monday <- 22.25
pay.Tuesday <- 8.50
pay.Wednesday <- 9.50
pay.Thursday <- 8.00
pay.Friday <- 10.00
printfn "Payroll Preparation"
printfn "------------------------"
printfn "Weekly Salary: %0.02f" (validate staff pay true)
This would produce:
Payroll Preparation ------------------------ Weekly Salary: 962.00 Press any key to continue . . .
Classes and Classes
A Property of a Class Type
As a class can be made a member variable of another class, it can also be created as a property. The formula is the exact same we have seen for properties of primitive types. Here are examples:
type Rectangle() =
let mutable len = 0.00
let mutable wd = 0.00
member this.Length with get() = len and set(value) = len <- value
member this.Width with get() = wd and set(value) = wd <- value
member this.Perimeter with get() = (len + wd) * 2.00
member this.Area with get() = len * wd
type Circle() =
let mutable radius = 0.00
member me.Radius with get() = radius and set(value) = radius <- value
member me.Diameter with get() = radius * 2.00
member me.Circumference with get() = me.Diameter * 3.14156
member me.Area with get() = radius * radius * 3.14156
type BasketballCourt() =
let mutable external = new Rectangle()
let mutable central = new Circle()
let mutable rar = 0.00
let mutable rh = 0.00
let mutable kw = 0.00
let mutable ftld = 0.00
let mutable b3pld = 0.00
member sport.Court
with get() = external
and set(value) = external <- value
member sport.Center
with get() = central
and set(value) = central <- value
member sport.RestrictedArcRadius
with get() = rar
and set(value) = rar <- value
member sport.RimHeight
with get() = rh
and set(value) = rh <- value
member sport.KeyWidth
with get() = kw
and set(value) = kw <- value
member sport.FreeThrowLineDistance
with get() = ftld
and set(value) = ftld <- value
member sport.B3PointLineDistanceFromBasket
with get() = b3pld
and set(value) = b3pld <- value
let NBACourt = BasketballCourt()
let NBA = Rectangle()
NBA.Length <- 28.65
NBA.Width <- 15.24
NBACourt.Court <- NBA
NBACourt.RimHeight <- 3.05;
NBACourt.RestrictedArcRadius <- 1.22;
let courtCenter = Circle()
courtCenter.Radius <- 1.22;
NBACourt.Center <- courtCenter
NBACourt.B3PointLineDistanceFromBasket <- 1.22;
NBACourt.KeyWidth <- 4.88;
NBACourt.FreeThrowLineDistance <- 4.57;
printfn "Basketball Court"
printfn "_____________________________________________________"
printfn "Court Measures ______________________________________"
printfn " Length: %0.02f m" NBACourt.Court.Length
printfn " Width: %0.02f m" NBACourt.Court.Width
printfn " Perimeter: %0.02f m" NBACourt.Court.Perimeter
printfn " Area: %0.02f m" NBACourt.Court.Area
printfn "Central Circle Measures ____________________________"
printfn " Radius: %0.02f m" NBACourt.Center.Radius
printfn " Diameter: %0.02f m" NBACourt.Center.Diameter
printfn " Circumference: %0.02f m" NBACourt.Center.Circumference
printfn " Area: %0.02f m" NBACourt.Center.Area
printfn "____________________________________________________"
printfn "Restricted Arc Radius: %0.02f m" NBACourt.RestrictedArcRadius
printfn "3-Point Line Distance From Basket: %0.02f m" NBACourt.B3PointLineDistanceFromBasket
printfn "Key Width (Shaded Lane or Restricted Area: %0.02f m" NBACourt.KeyWidth
printfn "Free-throw line distance from point on the floor directly below the backboard: %0.02f m" NBACourt.FreeThrowLineDistance
printfn "____________________________________________________"
This would produce:
Basketball Court _____________________________________________________ Court Measures ______________________________________ Length: 28.65 m Width: 15.24 m Perimeter: 87.78 m Area: 436.63 m Central Circle Measures ____________________________ Radius: 1.22 m Diameter: 2.44 m Circumference: 7.67 m Area: 4.68 m ____________________________________________________ Restricted Arc Radius: 1.22 m 3-Point Line Distance From Basket: 1.22 m Key Width (Shaded Lane or Restricted Area: 4.88 m Free-throw line distance from point on the floor directly below the backboard: 4 .57 m ____________________________________________________ Press any key to continue . . .
If the class that represents the property has an appropriate constructor, you can pass a parameter of that class to the constructor of your new class and use that argument in the property. Here are examples:
type Rectangle(length, width) = let mutable len = length let mutable wd = width member this.Length with get() = length and set(value) = len <- value member this.Width with get() = width and set(value) = wd <- value member this.Perimeter with get() = (len + wd) * 2.00 member this.Area with get() = len * wd type Circle(radius) = let mutable rad = radius member me.Radius with get() = radius and set(value) = rad <- value member me.Diameter with get() = rad * 2.00 member me.Circumference with get() = me.Diameter * 3.14156 member me.Area with get() = rad * rad * 3.14156 type BasketballCourt(rect, circle) = let mutable external = rect let mutable central = circle let mutable rar = 0.00 let mutable rh = 0.00 let mutable kw = 0.00 let mutable ftld = 0.00 let mutable b3pld = 0.00 member sport.Court with get() = external and set(value) = external <- value member sport.Center with get() = central and set(value) = central <- value member sport.RestrictedArcRadius with get() = rar and set(value) = rar <- value member sport.RimHeight with get() = rh and set(value) = rh <- value member sport.KeyWidth with get() = kw and set(value) = kw <- value member sport.FreeThrowLineDistance with get() = ftld and set(value) = ftld <- value member sport.B3PointLineDistanceFromBasket twith get() = b3pld and set(value) = b3pld <- value let NBACourt = BasketballCourt(Rectangle(28.65, 15.24), Circle(1.22)) NBACourt.RimHeight <- 3.05; NBACourt.RestrictedArcRadius <- 1.22; NBACourt.B3PointLineDistanceFromBasket <- 1.22; NBACourt.KeyWidth <- 4.88; NBACourt.FreeThrowLineDistance <- 4.57; printfn "Basketball Court" printfn "_____________________________________________________" printfn "Court Measures ______________________________________" printfn " Length: %0.02f m" NBACourt.Court.Length printfn " Width: %0.02f m" NBACourt.Court.Width printfn " Perimeter: %0.02f m" NBACourt.Court.Perimeter printfn " Area: %0.02f m" NBACourt.Court.Area printfn "Central Circle Measures ____________________________" printfn " Radius: %0.02f m" NBACourt.Center.Radius printfn " Diameter: %0.02f m" NBACourt.Center.Diameter printfn " Circumference: %0.02f m" NBACourt.Center.Circumference printfn " Area: %0.02f m" NBACourt.Center.Area printfn "____________________________________________________" printfn "Restricted Arc Radius: %0.02f m" NBACourt.RestrictedArcRadius printfn "3-Point Line Distance From Basket: %0.02f m" NBACourt.B3PointLineDistanceFromBasket printfn "Key Width (Shaded Lane or Restricted Area: %0.02f m" NBACourt.KeyWidth printfn "Free-throw line distance from point on the floor directly below the backboard: %0.02f m" NBACourt.FreeThrowLineDistance printfn "____________________________________________________"
A Method that Returns an Object
A method of a class can be made to produce an object of a class type. Here is an example:
type TimePeriod =
| LunchSpecial
| RegularLunch
| Dinner
type Meal(name, description, price) =
let mutable n = name
let mutable d = description
let mutable p = price
member this.Name with get() = n and set(value) = n <- value
member this.Description with get() = d and set(value) = d <- value
member this.UnitPrice with get() = p and set(value) = p <- value
type MealOrder(name : string, period : TimePeriod) =
let getMeal() : Meal =
if name = "LS01" then Meal("LS01", "Sweet and Sour Chicken", 5.95)
elif name = "LS02" then Meal("LS02", "Mongolian Beef", 5.95)
elif name = "LS03" then Meal("LS03", "Cashew Shrimp", 7.25)
else Meal("", "", 0.00)
member this.Present() =
printfn "Customer Order"
printfn "------------------------------------------"
printfn "Time Period: %A" period
printfn "Selection: %s" (getMeal().Name)
printfn "Price: %0.02f" (getMeal().UnitPrice)
let order = MealOrder("LS01", TimePeriod.LunchSpecial)
order.Present()
This would produce:
Customer Order ------------------------------------------ Time Period: LunchSpecial Selection: LS01 Price: 5.95 Press any key to continue . . .
Passing an Object to a Method
Depending on its role, an object can be passed to a method of a class. Such an object can be used only in the body of the method. Here is an example:
type TimePeriod =
| LunchSpecial
| RegularLunch
| Dinner
type Meal(name, description, price) =
let mutable n = name
let mutable d = description
let mutable p = price
member this.Name with get() = n and set(value) = n <- value
member this.Description with get() = d and set(value) = d <- value
member this.UnitPrice with get() = p and set(value) = p <- value
type MealOrder(name, period : TimePeriod, spicy) =
member this.PresentOrder(food : Meal) =
if food.Name = name then
printfn "Customer Order"
printfn "------------------------------------------"
printfn "Time Period: %A" period
printfn "Selection: %s" food.Name
printfn "Spicy? %A" spicy
printfn "Price: %0.02f" food.UnitPrice
else
printfn "Wrong Selection: The food name you provided is not valid."
let ls01 = Meal("LS01", "Sweet and Sour Chicken", 5.95)
let rl01 = Meal("RL01", "Sweet and Sour Chicken", 8.95)
let ls02 = Meal("LS02", "Mongolian Beef", 5.95)
let rl02 = Meal("RL02", "Mongolian Beef", 9.95)
let ls03 = Meal("LS03", "Cashew Shrimp", 7.25)
let unknown = Meal("", "", 0.00)
let order = MealOrder("RL02", TimePeriod.RegularLunch, true)
order.PresentOrder(rl02)
This would produce:
Customer Order ------------------------------------------ Time Period: RegularLunch Selection: RL02 Spicy? true Price: 9.95
In the same way, you can create a class whose constructor takes an object as parameter. That allows you to use the parameter object throughout the body of the class. Here is an example:
type TimePeriod =
| LunchSpecial
| RegularLunch
| Dinner
type Meal(name, description, price) =
let mutable n = name
let mutable d = description
let mutable p = price
member this.Name with get() = n and set(value) = n <- value
member this.Description with get() = d and set(value) = d <- value
member this.UnitPrice with get() = p and set(value) = p <- value
type MealOrder(food : Meal, period : TimePeriod)
member this.PresentOrder() =
printfn "Customer Order"
printfn "------------------------------------------"
printfn "Time Period: %A" period
printfn "Selection: %s" food.Name
printfn "Price: %0.02f" food.UnitPrice
let ls01 = Meal("LS01", "Sweet and Sour Chicken", 5.95)
let rl01 = Meal("RL01", "Sweet and Sour Chicken", 8.95)
let ls02 = Meal("LS02", "Mongolian Beef", 5.95)
let rl02 = Meal("RL02", "Mongolian Beef", 9.95)
let ls03 = Meal("LS03", "Cashew Shrimp", 7.25)
let unknown = Meal("", "", 0.00)
let order = MealOrder(rl02, TimePeriod.RegularLunch)
order.PresentOrder()
This would produce:
Customer Order ------------------------------------------ Time Period: RegularLunch Selection: RL02 Price: 9.95 Press any key to continue . . .
Passing an Interface to a Function or Method
An interface provides a list of members that some classes must implement. After creating such classes, you can create a function or method that gets the interface as a parameter. In the body of the function or method, through the parameter, you can access only the members of the interface. When calling the function or method that receives the interface, you must pass an object of a class that implements the interface. Here are examples:
type ICircular =
abstract Diameter : unit -> double
abstract Circumference : unit -> double
abstract Area : unit -> double
type IQuadrilateralArea =
abstract Area : double * double -> double
type Circle(radius : double) =
member this.Radius : double = radius
member this.Diameter() = (this :> ICircular).Diameter()
member this.Circumference() = (this :> ICircular).Circumference()
member this.Area() = (this :> ICircular).Area()
interface ICircular with
member this.Diameter() = radius * 2.00
member this.Circumference() = radius * 2.00 * 3.14156
member this.Area() : double = radius * radius * 3.14156
type Sphere(radius : double) =
member this.Radius : double = radius
member this.Diameter() = (this :> ICircular).Diameter()
member this.Circumference() = (this :> ICircular).Circumference()
member this.Area() = (this :> ICircular).Area()
interface ICircular with
member this.Diameter() = radius * 2.00
member this.Circumference() = radius * 2.00 * 3.14156
member this.Area() : double = radius * radius * 4.00 * 3.14156
type Cylinder(radius : double, height : double) =
member this.Radius : double = radius
member this.Height : double = height
member this.Diameter() = (this :> ICircular).Diameter()
member this.Circumference() = (this :> ICircular).Circumference()
member this.BottomArea() = (this :> ICircular).Area()
interface ICircular with
member this.Diameter() = radius * 2.00
member this.Circumference() = radius * 2.00 * 3.14156
member this.Area() : double = radius * radius * 3.14156
interface IQuadrilateralArea with
member this.Area(length : double, width : double) : double = length * width
let describe(round : ICircular) =
printfn "Round Shape Characteristics";
printfn "------------------------------";
printfn "Diameter: %f" (round.Diameter());
printfn "Circumference: %f" (round.Circumference());
printfn "Area: %f" (round.Area());
printfn "==============================";
let circle = Circle(46.8506)
let ball = Sphere(46.8506)
let cup = Cylinder(46.8506, 28.96)
describe circle
describe ball
describe cup
This would produce:
Round Shape Characteristics ------------------------------ Diameter: 93.701200 Circumference: 294.367942 Area: 6895.657349 ============================== Round Shape Characteristics ------------------------------ Diameter: 93.701200 Circumference: 294.367942 Area: 27582.629395 ============================== Round Shape Characteristics ------------------------------ Diameter: 93.701200 Circumference: 294.367942 Area: 6895.657349 ============================== Press any key to continue . . .
Because F# is top-down one directional language (somehow like C++ and Java but unlike C#), if you want to access the members of a class that implements the interface, you must declare its variable before defining the function or method that takes the interface as parameter. Here are examples:
type ICircular = abstract Diameter : unit -> double abstract Circumference : unit -> double abstract Area : unit -> double type IQuadrilateralArea = abstract Area : double * double -> double type Circle(radius : double) = member this.Radius : double = radius member this.Diameter() = (this :> ICircular).Diameter() member this.Circumference() = (this :> ICircular).Circumference() member this.Area() = (this :> ICircular).Area() interface ICircular with member this.Diameter() = radius * 2.00 member this.Circumference() = radius * 2.00 * 3.14156 member this.Area() : double = radius * radius * 3.14156 type Sphere(radius : double) = member this.Radius : double = radius member this.Diameter() = (this :> ICircular).Diameter() member this.Circumference() = (this :> ICircular).Circumference() member this.Area() = (this :> ICircular).Area() interface ICircular with member this.Diameter() = radius * 2.00 member this.Circumference() = radius * 2.00 * 3.14156 member this.Area() : double = radius * radius * 4.00 * 3.14156 type Cylinder(radius : double, height : double) = member this.Radius : double = radius member this.Height : double = height member this.Diameter() = (this :> ICircular).Diameter() member this.Circumference() = (this :> ICircular).Circumference() member this.BottomArea() = (this :> ICircular).Area() interface ICircular with member this.Diameter() = radius * 2.00 member this.Circumference() = radius * 2.00 * 3.14156 member this.Area() : double = radius * radius * 3.14156 interface IQuadrilateralArea with member this.Area(length : double, width : double) : double = length * width let circle = Circle(46.8506) let describeCircle(round : ICircular) = printfn "Circle Characteristics"; printfn "------------------------------"; printfn "Radius: %f" circle.Radius; printfn "Diameter: %f" (round.Diameter()); printfn "Circumference: %f" (round.Circumference()); printfn "Area: %f" (round.Area()); printfn "=============================="; let ball = Sphere(46.8506) let describeSphere(round : ICircular) = printfn "Sphere Characteristics"; printfn "------------------------------"; printfn "Radius: %f" ball.Radius; printfn "Diameter: %f" (round.Diameter()); printfn "Circumference: %f" (round.Circumference()); printfn "Area: %f" (round.Area()); printfn "=============================="; let cup = Cylinder(46.8506, 28.96) let describeCylinder(round : ICircular) = printfn "Cylinder Characteristics"; printfn "------------------------------"; printfn "Radius: %f" cup.Radius; printfn "Height: %f" cup.Height; printfn "Diameter: %f" (round.Diameter()); printfn "Circumference: %f" (round.Circumference()); printfn "Area: %f" (round.Area()); printfn "=============================="; describeCircle circle describeSphere ball describeCylinder cup
This would produce:
Circle Characteristics ------------------------------ Radius: 46.850600 Diameter: 93.701200 Circumference: 294.367942 Area: 6895.657349 ============================== Sphere Characteristics ------------------------------ Radius: 46.850600 Diameter: 93.701200 Circumference: 294.367942 Area: 27582.629395 ============================== Cylinder Characteristics ------------------------------ Radius: 46.850600 Height: 28.960000 Diameter: 93.701200 Circumference: 294.367942 Area: 6895.657349 ============================== Press any key to continue . . .
Passing a Class as Parameter to its Own Methods
An instance of a class can be passed as a parameter to one of its own methods. To do this, you primarily pass the parameter as if it were any class. Here is an example:
type Point() = member this.Equivalent (same : Point) = . . .
In the body of the method, do whatever you want. If you decide to use the parameter, all of the other members of the class are available through the parameter. Probably the simplest way to use the parameter is to assign each of its values to the equivalent member of the class. Here is an example:
type Point(x, y) = let mutable xCoordinate = x let mutable yCoordinate = y member this.X with get() = xCoordinate and set(value) = xCoordinate <- value member this.Y with get() = yCoordinate and set(value) = yCoordinate <- value member this.Equivalent (same : Point) = this.X <- same.X this.Y <- same.Y
When calling the method, make sure you pass an instance of the class to it. You can first create and define the class, then pass it. Here is an example:
type Point(x, y) = let mutable xCoordinate = x let mutable yCoordinate = y member this.X with get() = xCoordinate and set(value) = xCoordinate <- value member this.Y with get() = yCoordinate and set(value) = yCoordinate <- value new() = Point(0, 0) member this.Equivalent (same : Point) = this.X <- same.X this.Y <- same.Y let showPoint (pt : Point) = printfn "Point Coordinates: A(%d, %d)" pt.X pt.Y let pt = new Point() pt.X <- 4 pt.Y <- 6 showPoint pt let one = new Point() one.Equivalent pt showPoint(one)
This would produce:
Point Coordinates: A(4, 6) Point Coordinates: A(4, 6) Press any key to continue . . .
Instead of first declaring a variable of the class and initializing it, you can create an instance of the class in the parentheses of the calling method. To do this, you may need a constructor that can specify the values of the properties of the class so the argument can be rightfully initialized. Here is an example:
type Point(x, y) = let mutable xCoordinate = x let mutable yCoordinate = y member this.X with get() = xCoordinate and set(value) = xCoordinate <- value member this.Y with get() = yCoordinate and set(value) = yCoordinate <- value new() = Point(0, 0) member this.Equivalent (same : Point) = this.X <- same.X this.Y <- same.Y let showPoint (pt : Point) = printfn "Point Coordinates: A(%d, %d)" pt.X pt.Y let pt = new Point() pt.X <- 4 pt.Y <- 6 showPoint pt let one = new Point() one.Equivalent (Point(-3, 2)) showPoint(one)
This would produce:
Point Coordinates: A(4, 6) Point Coordinates: A(-3, 2)
Passing a Constructor
Instead of a formal method, you can use a constructor of the class to pass an instance of the same class. Then, in the constructor, use the argument as you see fit, knowing that all the members of the class are available. Here is an example:
type Point(x, y) = let mutable xCoordinate = x let mutable yCoordinate = y member this.X with get() = xCoordinate and set(value) = xCoordinate <- value member this.Y with get() = yCoordinate and set(value) = yCoordinate <- value new() = Point(0, 0) new(same : Point) = Point(same.X, same.Y) member this.Equivalent (same : Point) = this.X <- same.X this.Y <- same.Y
Obviously the purpose of passing a class to one of its own methods is not to find its equivalent. Instead, you can create a method that takes an instance of the same class but modifies that instance. For example, for our Point class, we may want to create a new point that is distanced by one unit from the current Point object. Here is an example of doing that:
type Point(x, y) = let mutable xCoordinate = x let mutable yCoordinate = y member this.X with get() = xCoordinate and set(value) = xCoordinate <- value member this.Y with get() = yCoordinate and set(value) = yCoordinate <- value new() = Point(0, 0) new(same : Point) = Point(same.X, same.Y) member this.Equivalent (same : Point) = this.X <- same.X this.Y <- same.Y member this.CreatePointOneUnitAway(addUnit : Point) = this.X <- addUnit.X + 1 this.Y <- addUnit.Y + 1 let showPoint(pt : Point) = printfn "Point Coordinates: A(%d, %d)" pt.X pt.Y let pt = new Point() pt.X <- 4 pt.Y <- 6 showPoint pt let one = new Point() one.CreatePointOneUnitAway pt showPoint one one.CreatePointOneUnitAway(Point(-8, -3)) showPoint one
This would produce:
Point Coordinates: A(4, 6) Point Coordinates: A(5, 7) Point Coordinates: A(-7, -2) Press any key to continue . . .
|
|||
Previous | Copyright © 2014-2024, FunctionX | Monday 14 February 2022 | Next |
|