简体   繁体   中英

One variable, one class and two of the same function swift

I have searched google for this answer for so long, until I created an account at stack overflow to ask this question.

How do you program a variable to hold a class with some variable in it then call the same function two times? Explained in the code:

class Persons {

var oldName = ""
var oldAge = 0
var oldGender = ""
var name = ""
var age = 0
var gender = ""

func create(_ name:String, _ age:Int, _ gender:String) -> String {

    if(age > 100) {
        print("Can't create a person with an age that is over 100!")

        return "Not created!"
    }

    if(gender == "Boy" || gender == "Girl") {

    }
    else {
        print("Gender has to be a girl or a boy!")

        return "Not created!"
    }
    self.name = name
    self.age = age
    self.gender = gender

    self.oldName = name
    self.oldAge = age
    self.oldGender = gender

    print("You just created a \(gender) called: '\(name)' with the age of: '\(age)'!")

    return "Created!"
}

func modify(_ targetName:String, _ newName:String, _ newAge:Int, _ newGender:String) -> String {

    if(age > 100) {
        print("Can't modify a person with an age that is over 100!")
        return "Not modified!"
    }

    if(gender == "Boy" || gender == "Girl") {

    }
    else {
        print("Gender has to be a girl or a boy!")
        return "Not modified!"
    }

    if(targetName != "" && targetName == self.name) {
        self.name = newName
        self.age = newAge
        self.gender = newGender

        print("You just changed \(oldName)'s gender from: \(oldGender) to: \(gender), \(oldName)'s name from: \(oldName) to: \(name) and \(oldName)'s age from: \(oldAge) to: \(age)!")
    }
    else {
        print("Please enter a valid target name or create one!")
    }

    return "Modified!"
}

func delete(_ targetName:String) -> String {

    if(name != "" && targetName == self.name) {
        print("Deleted: \(name)!")
    }
    else {
        print("Please enter a valid target name or create one!")
    }

    return "Deleted!"
}

}

var p = Persons()
p.create("Isak", 11, "Boy")
p.create("Sanne", 7, "Girl") // Here I create another person
p.delete("Isak") // But if I say delete 'Isak' it does not delete him because I created 'Sanne' above!

/*
It would work like this

p.create("Isak", 11, "Boy")
p.delete("Isak")
p.create("Sanne", 7, "Girl")
*/

Please help. I have spent ages to find the answer. If you need more details just reply and I will try to explain some more.

The problem here is that you are working with a single instance of Person. When you are doing:

p.create("Isak", 11, "Boy")
p.create("Sanne", 7, "Girl") // Here I create another person

You are not creating another person, despite you are just editing the properties of the p instance of Person class. So, when you are deleting Isak:

p.delete("Isak")

there are no Isak already, he was renamed to Sanne.

To solve this problem you should create two separate instances of Person:

var p1 = Persons()
var p2 = Persons()
p1.create("Isak", 11, "Boy")
p2.create("Sanne", 7, "Girl") // Here I create another instance of person
p1.delete("Isak")

At this state you have two persons: Sanne and Isak that you have just deleted and Sanne is still existing and is accessible.

If you want to use a single instance to hold all of your persons use this:

class Person {
var oldName = ""
var oldAge = 0
var oldGender = ""
var name = ""
var age = 0
var gender = ""

func create(_ name:String, _ age:Int, _ gender:String) -> String {

    if(age > 100) {
        print("Can't create a person with an age that is over 100!")

        return "Not created!"
    }

    if(gender == "Boy" || gender == "Girl") {

    }
    else {
        print("Gender has to be a girl or a boy!")

        return "Not created!"
    }
    self.name = name
    self.age = age
    self.gender = gender

    self.oldName = name
    self.oldAge = age
    self.oldGender = gender

    print("You just created a \(gender) called: '\(name)' with the age of: '\(age)'!")

    return "Created!"
}

func modify(_ targetName:String, _ newName:String, _ newAge:Int, _ newGender:String) -> String {

    if(age > 100) {
        print("Can't modify a person with an age that is over 100!")
        return "Not modified!"
    }

    if(gender == "Boy" || gender == "Girl") {

    }
    else {
        print("Gender has to be a girl or a boy!")
        return "Not modified!"
    }

    if(targetName != "" && targetName == self.name) {
        self.name = newName
        self.age = newAge
        self.gender = newGender

        print("You just changed \(oldName)'s gender from: \(oldGender) to: \(gender), \(oldName)'s name from: \(oldName) to: \(name) and \(oldName)'s age from: \(oldAge) to: \(age)!")
    }
    else {
        print("Please enter a valid target name or create one!")
    }

    return "Modified!"
}

func delete() -> String {
    return "Deleted!"
}
}

class Persons {
var personsDictionary = [String: Person]()
}

var persons = Persons()
var p1 = Person()
var p2 = Person()

p1.create("Isak", 11, "Boy")
p2.create("Sanne", 7, "Girl")

persons.personsDictionary[p1.name] = p1
persons.personsDictionary[p2.name] = p2

persons.personsDictionary["Isak"]?.delete()

Here we have a Person class (one that you defined in your question but with slightly changed delete() method) and Persons class that have a Dictionary of [String : Person] . The key of dictionary is your person's name and value is this person.

When we create a person instance we store it in personsDictionary and than we can access every person in that dictionary by person's name and an Optional will be returned on which we can call all of your defined methods.

You are trying to use a model object as a repository also.

You only need one simple model, for a simple model it is better to use a struct. This also gives you the initialiser for free

struct Person {
    var name = ""
    var age = 0
    var gender = ""
}

Note: Better to use an enum for gender...

enum Gender {
    case male, female
}

struct Person {
    var name = ""
    var age = 0
    var gender: Gender = .male
}

Then just use an array to manage a list

let simon = Person(name: "Simon", age: 20, gender: .male)
let isak = Person(name: "Isak", age: 11, gender: .male)

var people = [simon, isak]

print(people.count) // output: 2
people.remove(isak)
print(people.count) // output: 1

let sanne = Person(name: "Sanne", age: 7, gender: .female)
people.append(sanne)

I would suggest that you read through the documentation instantiation and arrays are quite basic. At the minimum read about classes, structs, instantiation and arrays.

Here is the beginning of how I would go about it...

First the class to handle everything:

class Person {
    /// An enum for gender so that you can only ever use the permissable values.
    public enum Gender {
        case male
        case female
    }

    /// An enum for the results so there are defined values to check (you could add more specific errors).
    public enum Result {
        case success
        case failed(_: String)
    }

    /// A structure to hold the details of each person.
    struct PersonData {
        var name: String
        var age: UInt
        var gender: Gender
    }

    /// The internal list of people.
    private var personList: [String: PersonData] = [:]

    /// A function to create a person.
    func create(_ name: String, _ age: UInt, _ gender: Gender) -> Result {
        guard personList[name] == nil else {
            print ("Person already created!")

            return .failed("Person already created!")
        }

        guard age <= 100 else {
            print("Can't create a person with an age that is over 100!")

            return .failed("Cannot have age over 100!")
        }

        let person = PersonData(name: name, age: age, gender: gender)
        personList[name] = person

        print("You just created a \(gender) called: '\(name)' with the age of: '\(age)'!")

        return .success
    }

    /// A function to modify a persons details in the list.
    func modify(_ targetName: String, _ newName: String, _ newAge: UInt, _ newGender: Gender) -> Result {
        guard let person = personList[targetName] else {
            print ("Person not found in list!")

            return .failed("Person not found!")
        }

        guard personList[newName] == nil else {
            print ("Person already exists in list!")

            return .failed("Person already exist in the list!")
        }

        if newAge > 100 {
            print("Can't modify a person with an age that is over 100!")

            return .failed("Cannot modify a person with an ager over 100!")
        }

        let oldName = person.name
        let oldAge = person.age
        let oldGender = person.gender

        if targetName != newName {
            personList.removeValue(forKey: targetName)
        }
        personList[newName] = PersonData(name: newName, age: newAge, gender: newGender)

        print("You just changed \(oldName)'s gender from: \(oldGender) to: \(person.gender), \(oldName)'s name from: \(oldName) to: \(person.name) and \(oldName)'s age from: \(oldAge) to: \(person.age)!")

        return .success
    }

    /// A function to delete a person from the list.
    func delete(_ targetName:String) -> Result {
        guard let _ = personList[targetName] else {
            print ("Person not found in list!")

            return .failed("Person not found in list!")
        }

        personList.removeValue(forKey: targetName)

        print("Deleted: \(targetName)!")

        return .success
    }

    /// A test function to print out the current list of people.
    func printList() {
        for (name, person) in personList {
            print ("\(name) is \(person.gender) and age \(person.age)")
        }
    }

    /// Bonus to allow you to get a persons full details using something like person[name].
    subscript(name: String) -> PersonData? {
        return personList[name]
    }
}

Now here is how you use it:

let people = Person()

// Create Isak.
var result = people.create("Isak", 11, .male)

// Here is how to detail with the results.
switch result {
case .success:
    // Do something when successfully created.
    print ("Result = Success")
case .failed(let reason):
    // Do something when failed to create.
    print ("Result = \(reason)")
}

// Create Sanne
result = people.create("Sanne", 7, .female)

// Print the list to check they are in there.
people.printList()

// Delete Isak from the list.
result = people.delete("Isak")

// Change Sanne's name to New Sanne and age to 8.
result = people.modify("Sanne", "New Sanne", 8, .female)

// Print the list to check what's in there.
people.printList()

// Bonus showing how to get a persons full details.
if let personData = people["New Sanne"] {
    print ("\(personData.name) is \(personData.gender) and age \(personData.age)")
} else {
    print ("Not Found!")
}

The results should be:

You just created a male called: 'Isak' with the age of: '11'!
Result = Success
You just created a female called: 'Sanne' with the age of: '7'!
Sanne is female and age 7
Isak is male and age 11
Deleted: Isak!
You just changed Sanne's gender from: female to: female, Sanne's name from: Sanne to: Sanne and Sanne's age from: 7 to: 7!
New Sanne is female and age 8
New Sanne is female and age 8

I might also go further with it but that should be enough to get you started.

(Hopefully the comments explain what it going on but if not feel free to ask)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM