Custom initiations in Swift - Is there a way to 'not' initialize certain properties in a method? - swift

So my question is: Is there a way to create a custom initializer like below without initializing the other properties in the structure? I get an error within the custom initialization below because I am not giving values to the other two properties in the structure.
So my goal would be to create an instance of this structure, and only give values to three properties.
EX:
var starbucks = Coffee(caffeineAmountMg: 1200, countryOfOrigin: "South America", taste: "bad")
I just started coding a few days ago, so I apologize if there is a big lapse in my logic here, just trying to test out a few different things to make sure I understand everything I've learned so far.
struct Coffee {
var caffeineAmountMg: Int
init(caffeineAmountMg: Int) {
self.caffeineAmountMg = caffeineAmountMg
caffeineAmountG = caffeineAmountMg / 1000
}
var caffeineAmountG: Int
init(caffeineAmountG: Int) {
self.caffeineAmountG = caffeineAmountG
caffeineAmountMg = caffeineAmountG * 1000
}
var countryOfOrigin: String
var taste: String
}

One solution in this particular case is to store the quantity in a normalized form, and compute the other form(s). Let's say we store the quantity is milligrams. So:
struct Coffee {
init(caffeineAmountMg: Int, countryOfOrigin: String, taste: String) {
self.caffeineAmountMg = caffeineAmountMg
self.countryOfOrigin = countryOfOrigin
self.taste = taste
}
convenience init(caffeineAmountG: Int, countryOfOrigin: String, taste: String) {
self.init(caffeineAmountMg: caffeineAmountG * 1000, countryOfOrigin: countryOfOrigin, taste: taste)
}
var caffeineAmountMg: Int
var caffeineAmountG: Int {
get { return caffeineAmountMg / 1000 }
set { caffeineAmountMg = newValue * 1000 }
}
var countryOfOrigin: String
var taste: String
}
let cup = Coffee(caffeineAmountG: 1, countryOfOrigin: "South America is actually a continent", taste: "bad")
A variation on this style is to factor out the unit conversion into a separate type:
struct Mass {
let µg: Int
var mg: Int { return µg / 1_000 }
var g: Int { return µg / 1_000_000 }
private init(µg: Int) { self.µg = µg }
static func µg(_ µg: Int) -> Mass { return Mass(µg: µg) }
static func mg(_ mg: Int) -> Mass { return Mass(µg: mg * 1_000) }
static func g(_ g: Int) -> Mass { return Mass(µg: g * 1_000_000) }
}
struct Coffee {
init(caffeineAmount: Mass, countryOfOrigin: String, taste: String) {
self.caffeineAmount = caffeineAmount
self.countryOfOrigin = countryOfOrigin
self.taste = taste
}
var caffeineAmount: Mass
var countryOfOrigin: String
var taste: String
}
let cup = Coffee(caffeineAmount: .mg(10), countryOfOrigin: "South America is actually a continent", taste: "bad")

Yes, it can be done. The key to creating and initializing an object in Swift is to give all the variables values, i.e., initialize all of the object's variables to contain a valid value. The compiler will complain otherwise.
If you're not sure of the value of a certain variable, or if you would like to initialize a set of other variables, you can declare the unwanted variable as Optional, for ex.
var caffeineAmountG: Int?
An Optional variable means that it can either contain a valid value (Int in this case), or it can contain nil. In your init method, if you do not give any value to your Optional variable, it will be, by default initialised to nil automatically by the compiler.
So just as you wanted, you can have your struct initialised in a simple manner like so:
struct Coffee {
var caffeineAmountMg: Int
var caffeineAmountG: Int? //Considered caffeineAmountG = nil
var countryOfOrigin: String
var taste: String
init(caffeineAmountMg:Int, countryOfOrigin:String, taste:String) {
self.caffeineAmountMg = caffeineAmountMg
self.countryOfOrigin = countryOfOrigin
self.taste = taste
}
}
let coffee = Coffee(caffeineAmountMg: 32320, countryOfOrigin: "Country", taste: "Taste")
You can also - instead of initialising the variable to nil - provide any default value like this (without declaring it Optional):
var caffeineAmountG: Int = 0
Or you can compute it (caffeineAmountG) as you initialise your other variables:
init(caffeineAmountMg:Int, countryOfOrigin:String, taste:String) {
self.caffeineAmountMg = caffeineAmountMg
self.countryOfOrigin = countryOfOrigin
self.taste = taste
self.caffeineAmountG = self.caffeineAmountMg / 1000 //Converting Milligram to Gram
}
So according to the above init method, if we print the initialized object, it will contain the following values:
Coffee(caffeineAmountMg: 32320,
caffeineAmountG: 32,
countryOfOrigin: "Country",
taste: "Taste")

To follow up on #Paulw11 comment to use Measurement.
This keeps your exact API. You could improve things by making caffeineAmount public, and getting rid of caffeineAmountMg or caffeineAmountG.
struct Coffee {
var caffeineAmountMg: Int {
get { return Int(caffeineAmount.converted(to: UnitMass.milligrams).value) }
set { caffeineAmount = Measurement(value: Double(newValue), unit: UnitMass.milligrams) }
}
init(caffeineAmountMg: Int, countryOfOrigin: String, taste: String) {
self.caffeineAmount = Measurement(value: Double(caffeineAmountMg), unit: UnitMass.milligrams)
self.countryOfOrigin = countryOfOrigin
self.taste = taste
}
var caffeineAmountG: Int {
get { return Int(caffeineAmount.converted(to: UnitMass.grams).value) }
set { caffeineAmount = Measurement(value: Double(newValue), unit: UnitMass.grams) }
}
init(caffeineAmountG: Int, countryOfOrigin: String, taste: String) {
caffeineAmount = Measurement(value: Double(caffeineAmountG), unit: UnitMass.grams)
self.countryOfOrigin = countryOfOrigin
self.taste = taste
}
var countryOfOrigin: String
var taste: String
private var caffeineAmount: Measurement<UnitMass>
}

Related

Accept Float, Double or Int in Swift `init` to convert to String

I'm attempting to convert a value to a string in an init. That value can be an Int, Double, or Float.
For example:
struct example {
var string: String
init(number: Int) {
string = String(number)
}
}
I would like to say something like below (I'm using Typescript as an example - this obviously doesn't work, but I want number to be any of those three types - all of which String can convert).
struct example {
var string: String
init(number: Int | Float | Double) {
string = String(number)
}
}
Edit: I realized I have another issue. I need to convert back from a string to the type of Int or Double or Float. Using one of the answers below, I'm trying to figure out how to implement getNumberWith5:
struct example2<N: Numeric & CustomStringConvertible>: CustomStringConvertible {
#Binding var number: N
init(number: Binding<N>) {
self._number = number
}
var description: String {
String(describing: number)
}
mutating func getNumberWith5() {
// How do I update number to the type N?
self.number = howDoIConvertToN(description + "5")
}
}
Or from another answer:
struct example3<N: Numeric> {
#Binding var number: N
var string: String
init(number: Binding<N>) {
self._number = number
self.string = "\(number)"
}
mutating func getNumberWith5() {
// How do I update number to the type N?
self.number = howDoIConvertToN(string + "5")
}
}
Edit2 My Answer:
I attempted to create an equivalent of type unions (as Typescript has) using enums in Swift based on this article. But it was challenging to then assign back to that value. I've decided Swift just doesn't have first class support for type unions like Typescript has. So, I used the accepted answer below and this seems to work.
extension String {
func numeric<N: Numeric & LosslessStringConvertible>() -> N? {
N(self)
}
}
struct example4<N: Numeric & LosslessStringConvertible> {
#State var string: String
#Binding var number: N
init(number: Binding<N>) {
self._number = number
self.string = String(describing: number)
}
mutating func getNumberWith5() {
let newString = string + "5"
number = newString.numeric() ?? 0
}
}
Actually if all you want is a string representation of Int Float Double or any other standard numeric type you only need to know that they conform to CustomStringConvertible and use String(describing:).
Or you can use conformance to Numeric and CustomStringConvertible:
struct example {
var string: String
init<C: CustomStringConvertible & Numeric>(number: C) {
string = String(describing: number)
}
}
and maybe even better example itself could conform to CustomStringConvertible
struct example: CustomStringConvertible {
var description: String
init<C: CustomStringConvertible & Numeric>(number: C) {
description = String(describing: number)
}
}
yet another way :
struct example<N: Numeric & CustomStringConvertible>: CustomStringConvertible {
let number: N
init(number: N) {
self.number = number
}
var description: String {
String(describing: number)
}
}
EDIT
I think what you want is a custom Property Wrapper not #Binding:
#propertyWrapper struct CustomStringConversion<Wrapped: CustomStringConvertible> {
var wrappedValue: Wrapped
init(wrappedValue: Wrapped) {
self.wrappedValue = wrappedValue
}
var projectedValue: String { .init(describing: wrappedValue) }
}
struct Foo {
#CustomStringConversion var number = 5
}
let foo = Foo()
let number: Int = foo.number // 5
let stringRepresentation: String = foo.$number // "5"
But as #LeoDabus pointed out using LosslessStringConvertible may be better :
struct example<N: Numeric & LosslessStringConvertible>: LosslessStringConvertible {
let number: N
init(number: N) {
self.number = number
}
init?(_ description: String) {
guard let number = N(description) else { return nil }
self.number = number
}
var description: String {
.init(number)
}
}
let bar = example(number: Double.greatestFiniteMagnitude) // 1.7976931348623157e+308
let baz: example<Double>? = example("1.7976931348623157e+308") // 1.7976931348623157e+308
Use generic structure with Numeric protocol.
struct Example<T:Numeric> {
var string: String
init(number: T) {
self.string = "\(number)"
}
}
struct Example {
var string: String
init(number: Int) {
string = String(number)
}
init(number: Float) {
string = String(number)
}
init(number: Double) {
string = String(number)
}
}
You can have a look at how swift does this with its String-initializer:
struct Example {
init<Number>(number: Number) where Number: BinaryInteger {
string = String(number)
}
}

Why is my kg/lb conversion returning 0?

My function is used to convert between kilograms and pounds. For some unknown reason, the converted(to:) method seems to be either returning 0 (which I think is unlikely) or the assignment of the returned value to liftWeight isn't working.
func convertUnit(liftEvent: LiftEventRepresentable ) -> LiftEventRepresentable {
let unit = liftEvent.liftWeight.unit.symbol
switch unit {
case "kg":
let weight = liftEvent.liftWeight
print("Event weight is \(weight)") // 110.0 kg
let liftWeight = weight.converted(to: .pounds) // this is returning 0 or the assignment isn't working
print("The new weight is \(liftWeight)") 0.0 lb
liftEvent.updateWeightLifted(liftWeight.value)
liftEvent.updateWeightUnit(liftEvent.liftWeight.unit.symbol)
return liftEvent
case "lb":
// I'll finish this case after I get case "kg": working
default:
fatalError("Oops, this should not happen")
}
}
I thought it might be similar to a problem I had in the past which involved trying to assign a Measurement to an optional but I don't have any optional values in this method so I assume I must be doing something else wrong.
LiftEvent:
extension LiftEvent {
#NSManaged var date: Date
#NSManaged var repetitions: NSNumber
#NSManaged var uid: NSNumber?
#NSManaged var weightLifted: NSNumber
#NSManaged var weightUnit: String
#NSManaged var formula: Formula
#NSManaged var lift: Lift
}
The LiftEventRepresentable protocol is:
#objc protocol LiftEventRepresentable {
var date: Date { get }
var formula: Formula { get }
var repetitions: NSNumber { get set }
var liftWeight: Measurement<UnitMass> { get }
var maxWeight: Double { get }
var lift: Lift { get }
var context: NSManagedObjectContext { get }
var userDidChangeUnits: Bool { get set }
func updateWeightLifted(_ weight: Double)
func updateRepetitions(_ repetitions: Int)
func updateMaxAmount(_ maxAmount: Measurement<UnitMass>) -> ()
func updateLiftEventFormula(_ newFormulaUuid: String) -> ()
func updateLift(_ newLiftUuid: String) -> ()
func updateWeightUnit(_ newUnit: String)
func calculateOneRepMax() -> Measurement<UnitMass>
func updateLiftEventWithFinalValues()
}
Can anyone tell me why liftEvent.liftWeightis 0.0 lb after the conversion?
EDIT 1: This is how liftEvent.liftWeight is produced (which I should have included in my question originally). It's a computed property and I've now learning it's what causes the conversion to always return 0):
class LiftEvent: NSManagedObject, LiftEventRepresentable {
var liftWeight: Measurement<UnitMass> {
let defaultUnit = UserDefaults.weightUnit() // returns a string ("kg" or "lb")
let unitSymbol = UnitMass.init(symbol: defaultUnit) // the wrong way
let liftWeight = Measurement<UnitMass>(value: Double(weightLifted), unit: unitSymbol)
return liftWeight
}
EDIT 2: The root problem was, indeed, the liftEvent.liftWeight being invalid.
This is my new code which now works:
var liftWeight: Measurement<UnitMass> {
let defaultUnit = UserDefaults.weightUnit() // returns a string ("kg" or "lb")
let unit: UnitMass
if defaultUnit == "kg" {
unit = UnitMass.kilograms // the right way
} else {
unit = UnitMass.pounds // also the right way
}
let liftWeight = Measurement<UnitMass>(value: Double(weightLifted), unit: unit)
return liftWeight
}
Something is wrong with your Measurement's unit. It's a UnitMass so it has the correct dimension, but its converter is missing. This is probably because you created it using something like UnitMass(symbol: "kg") instead of UnitMass.kilograms.
// right way
let goodUnit = UnitMass.kilograms
let goodWeight:Measurement = Measurement(value: 110.0, unit: goodUnit)
print("Good pounds: ", goodWeight.converted(to: .pounds)) // 242.508686220216 lb
// wrong way (results in 0.0 output)
let badUnit = UnitMass(symbol: "kg")
let badWeight:Measurement = Measurement(value: 110.0, unit: badUnit)
print("Bad pounds: ", badWeight.converted(to: .pounds)) // 0.0 lb
Creating a unit with UnitMass(symbol: "kg") is actually valid code, so there's no error. You can use this syntax to create your own mass units with any symbol you want and a custom converter. For some reason the converter: parameter is optional, so UnitMass(symbol: "kg") just makes a new mass unit with the symbol "kg" and a default UnitLinearConverter with a coefficient of 0.
Using UnitMass.kilograms instead gives you a predefined kilogram unit that's already setup with the correct symbol and converter. Easy mistake to make, especially since there's no error.
I recommend taking a look at where you create liftEvent.liftWeight, as that is likely where the problem lies.

Swift: The proper way to initialize model class with a lot of properties

How do you initialize your classes/structs with a lot of properties?
This question could probably be asked without Swift context but Swift brings a flavour to it, so I add Swift tag in headline and tags.
Let's say you have a User class with 20 properties. Most of them should not be nil or empty. Let's assume these properties are not interdependent. Let's assume that 33% of it should be constant (let) by the logic of the class. Let's assume that at least 65% of them do not have meaningful default values. How would you design this class and initialize an instance of it?
So far I have few thoughts but none of it seems to be completely satisfactory to me:
put all of the properties linearly in the class and make huge init method:
class User {
// there is 20 properties like that
let id : String
let username : String
let email : String
...
var lastLoginDate : Date
var lastPlayDate : Date
// then HUUUUGE init
init(id: String,
username: String,
...
lastPlayDate: Date) {
}
}
try to group properties into sub types and deal with smaller inits separately
class User {
struct ID {
let id : String
let username : String
let email : String
}
struct Activity {
var lastLoginDate : Date
var lastPlayDate : Date
}
let id : ID
...
var lastActivity : Activity
// then not so huge init
init(id: ID,
...
lastActivity: Activity) {
}
}
another solution is to break requirements a bit: either declare some of the properties optional and set values after init or declare dummy default values and set normal values after init, which conceptually seems to be the same
class User {
// there is 20 properties like that
let id : String
let username : String
let email : String
...
var lastLoginDate : Date?
var lastPlayDate : Date?
// then not so huge init
init(id: String,
username: String,
email: String) {
}
}
// In other code
var user = User(id: "1", username: "user", email: "user#example.com"
user.lastLoginDate = Date()
Is there a nice paradigm/pattern how to deal with such situations?
You can try the builder pattern.
Example
class DeathStarBuilder {
var x: Double?
var y: Double?
var z: Double?
typealias BuilderClosure = (DeathStarBuilder) -> ()
init(buildClosure: BuilderClosure) {
buildClosure(self)
}
}
struct DeathStar : CustomStringConvertible {
let x: Double
let y: Double
let z: Double
init?(builder: DeathStarBuilder) {
if let x = builder.x, let y = builder.y, let z = builder.z {
self.x = x
self.y = y
self.z = z
} else {
return nil
}
}
var description:String {
return "Death Star at (x:\(x) y:\(y) z:\(z))"
}
}
let empire = DeathStarBuilder { builder in
builder.x = 0.1
builder.y = 0.2
builder.z = 0.3
}
let deathStar = DeathStar(builder:empire)
Example taken from here: https://github.com/ochococo/Design-Patterns-In-Swift
If you are looking for a bit more Java like solution, you can try something like this.
Alternative Example
final class NutritionFacts {
private let servingSize: Int
private let servings: Int
private let calories: Int
private let fat: Int
private let sodium: Int
private let carbs: Int
init(builder: Builder) {
servingSize = builder.servingSize
servings = builder.servings
calories = builder.calories
fat = builder.fat
sodium = builder.sodium
carbs = builder.carbs
}
class Builder {
let servingSize: Int
let servings: Int
private(set) var calories = 0
private(set) var fat = 0
private(set) var carbs = 0
private(set) var sodium = 0
init(servingSize: Int, servings: Int) {
self.servingSize = servingSize
self.servings = servings
}
func calories(value: Int) -> Builder {
calories = value
return self
}
func fat(value: Int) -> Builder {
fat = value
return self
}
func carbs(value: Int) -> Builder {
carbs = value
return self
}
func sodium(value: Int) -> Builder {
sodium = value
return self
}
func build() -> NutritionFacts {
return NutritionFacts(builder: self)
}
}
}
let facts = NutritionFacts.Builder(servingSize: 10, servings: 1)
.calories(value: 20)
.carbs(value: 2)
.fat(value: 5)
.build()
Example taken from: http://ctarda.com/2017/09/elegant-swift-default-parameters-vs-the-builder-pattern

Access variable of an enum nested in struct in a protocol extension in Swift

I am implementing a converter that easily converts double type parameters of a run into proper unit according to the provided unit style, metric or imperial. Distance is entered in meters which gets converted to km or miles according to the given unit style.
enum for two states of unit style
//enum to track the states of unit style
enum UnitStyle{
case Metric, Imperial
}
protocol implemented by every parameter of the run. This requires model to implement a type called Unit because every parameter has its own type of unit. e.g. For distance it can be out of km or mi whereas for speed it can be out of km/hr or mi/hr
//every parameter of run has to implement this protocol
protocol RunParameter{
typealias Unit: RawRepresentable
var value: Double{get set}
var unit: Unit{get}
var unitStyle: UnitStyle{get set}
}
This extension does all the magic. It multiplies the value of given run parameter to its suitable unit to obtain the correct value. Everything is fine till here. Now I need to get the unit description as well here in this method so that I can return it to display on the screen. For this I created a description variable inside the enum Unit but the problem is I can not access this description variable in protocol extension. In a nutshell only rawValue variable is available on self.unit no description variable inside protocol extension.
extension RunParameter where Unit.RawValue == Double{
mutating func getValueForUnitStyle(unitStyle: UnitStyle) -> Double{
self.unitStyle = unitStyle
return value * self.unit.rawValue
//here I want to return both calculated value and unit string
//but unable to access unit description on self.unit
}
}
struct Distance: RunParameter {
enum Unit: Double {
case km = 0.001
case m = 1.0
case mi = 0.000621371
var description: String{
switch self{
case .km: return "km"
case .m: return "m"
case .mi: return "mi"
}
}
}
var value: Double
var unitStyle = UnitStyle.Metric
var unit: Unit {
get{
switch unitStyle{
case .Metric: return Unit.km
case .Imperial: return Unit.mi
}
}
}
init(value: Double){
self.value = value
}
}
struct Run {
var unitStyle = UnitStyle.Imperial
var distance = Distance(value: 10.0)
}
description variable is available here. I can access description on x.distance.unit
var x = Run()
let z = x.distance.getValueForUnitStyle(.Imperial)
x.distance.unit.description //output "mi"
enum UnitStyle{
case Metric, Imperial
}
protocol RunParameter{
typealias Unit: RawRepresentable, CustomStringConvertible
var value: Double{get set}
var unit: Unit{get}
var unitStyle: UnitStyle{get set}
}
extension RunParameter where Unit.RawValue == Double{
mutating func getValueForUnitStyle(unitStyle: UnitStyle) -> (Double,String){
self.unitStyle = unitStyle
return (value * self.unit.rawValue, self.unit.description)
//here I want to return both calculated value and unit string
//but unable to access unit description on self.unit
}
}
struct Distance: RunParameter {
enum Unit: Double, CustomStringConvertible {
case km = 0.001
case m = 1.0
case mi = 0.000621371
var description: String{
switch self{
case .km: return "km"
case .m: return "m"
case .mi: return "mi"
}
}
}
var value: Double
var unitStyle = UnitStyle.Metric
var unit: Unit {
get{
switch unitStyle{
case .Metric: return Unit.km
case .Imperial: return Unit.mi
}
}
}
init(value: Double){
self.value = value
}
}
struct Run {
var unitStyle = UnitStyle.Imperial
var distance = Distance(value: 10.0)
}
var x = Run()
let z = x.distance.getValueForUnitStyle(.Imperial)
x.distance.unit.description //output "mi"
print(z.0,z.1) // 0.00621371 mi

Error:Missing argument for parameter 'makePetMakeNoise' in call

Hi I am doing some Swift coding and I cant figure out how to get rid of this error:
Missing argument for parameter 'makePetMakeNoise' in call.
Could you help me fix this error?
import Foundation
import UIKit
class Human {
static var numCreated:Int = 4
var name:String = ""
var pet:Pet
init(name:String,pet:Pet){
self.name = name
self.pet = pet
Human.numCreated++
}
func makePetMakeNoise(){
var randomNumber = arc4random_uniform(9)
self.pet.makeNoise(randomNumber) //Missing argument for parameter 'makePetMakeNoise' in call
}
func feedPet(){
self.pet.eat
}
static func populationCount(){
println("Total population count is \(Human.numCreated)")
}
}
class Pet {
var name:String = ""
var noise:String = ""
var canMakeNoise:Bool = true
init(name:String,noise:String,canMakeNoise:Bool){
self.name = name
self.noise = noise
self.canMakeNoise = canMakeNoise
}
func makeNoise(canMakeNoise: Int, makePetMakeNoise: Int){
if self.canMakeNoise {
for _ in 1...5{
println("\(self.name) \(self.noise)")
}
}else {
println("\(self.name) *remains silent*")
}
}
func eat(){
println("\(name) is eating")
}
class Dog:Pet{
}
class Cat:Pet{
override func eat {
super.eat()
println("I'm still hungry, meow")
}
}
}
//Pets
var Tobie = Pet(name: "Tobie", noise: "Bark", canMakeNoise: true)
var Bud = Pet(name: "Bud", noise: "Bark", canMakeNoise: false)
var Ginger = Pet(name: "Ginger", noise: "bark", canMakeNoise: false)
var Curry = Pet(name: "Curry", noise: "Bark", canMakeNoise: true)
//Humans
var Sam = Human(name: "Sam", pet: Tobie)
var Mark = Human(name: "Mark", pet: Bud)
var Spencer = Human(name: "Spencer", pet: Ginger)
var Jessie = Human(name: "Jessie", pet: Curry)
let Humans = [Sam, Mark, Spencer, Jessie]
for Human in Humans {
println("\(Humans) \(feedPet) \(makePetMakeNoise)") //Use of unresolved identifier 'feedPet and makePetMakeNoise'\\
}
`
Your makeNoise method defined for Pet takes two parameters. Problem is that when you call it in the line that gives you the error, you pass it just one parameter.
Possible solution is:
Change the Pet's method as follow:
func makeNoise(makePetMakeNoise: Int){
if self.canMakeNoise {
for _ in 1...5{
println("\(self.name) \(self.noise)")
}
}else {
println("\(self.name) *remains silent*")
}
}
Update the code that gives you the error in Human like this:
func makePetMakeNoise(){
var randomNumber = Int(arc4random_uniform(9))
self.pet.makeNoise(randomNumber)
}
Notice I convert random to Int since this is the expected parameter type.
Please consider I'm just guessing a possible modification since I don't know what your classes are intended for ... maybe just a playground.
Other solution is effectively passing two parameters when you call the pet's method from human.
Hope this helps
Your function func makeNoise(canMakeNoise: Int, makePetMakeNoise: Int) expects two arguments, but your are only passing the one randonNumber in your call self.pet.makeNoise(randomNumber). It should look something like this: self.pet.makeNoise(randomNumber, someOtherNumber)