Home > Software design >  Declare a structure which is inside a class
Declare a structure which is inside a class

Time:09-24

I've a class with a subclass and inside the subclass there's a struct. I want to call this struct by name. I want to declare a variable with those and give name number1 and number2 its own data.

class Main {
    var name:String
    init(name:String){
        self.name = name
    }
}
class SubMain: Main {
    override init(name:String){
        super.init(name: name)
    }
    struct Test {
        var number1:Int
        var number2:Int
    }
}

I've tried declaring subMain, and after declaring that I called Test struct but it doesn't work. Looking for solution:

var main2 = SubMain(name: "hello")
main2.Test(number1:15,number2:20)

CodePudding user response:

Your use case is a bit strange, the main reason for declaring an internal type within another type is that you want to use the internal type inside the outer type.

An example

class SubMain: Main {
    var test: Test?

    override init(name:String){
        super.init(name: name)
    }

    convenience init(name: String, test: Test) {
        self.init(name: name)
        self.test = test
    }

    struct Test {
        var number1:Int
        var number2:Int
    }
}

And then

var main2 = SubMain(name: "hello")
var main3 = SubMain(name: "world", test: .init(number1: 1, number2: 2))

But to use your example you should access it via the outer type and not an instance of that type

var test = SubMain.Test(number1: 1, number2: 2)

CodePudding user response:

You can do that, but you have to use the Main initializer and you have to reference the struct from outside the class with SubMain.Test

CodePudding user response:

It isn't clear what you want the line main2.Test(number1:15,number2:20) to do. Is that supposed to create a variable of type Test? (Or rather, SubMain.test)? Or is it supposed to replace your main2's .test property with a new value? Both are possible, but require slightly different syntax.

If you want your SubMain class to have an additional instance variable of type Test, you need to refactor your code slightly, as shown in Joakim's answer.

Take a look at this code:

class Main {
    var name:String
    init(name:String){
        self.name = name
    }
}
class SubMain: Main {
    
    // Declare a struct "Test", and have it conform to the `CustomStringConvertible` class so we can log `Test` values`
    struct Test: CustomStringConvertible {
        var number1:Int
        var number2:Int
        var description: String {
            return "Test(number1: \(self.number1), number2: \(self.number2))"
        }
    }

    var test: Test
    init(name:String, test: Test){
        self.test = test
        super.init(name: name)
    }
}

// Also Make our SubMain class conform to CustomStringConvertible
extension SubMain: CustomStringConvertible {
    var description: String {
        return "SubMain(name: \(self.name), test = \(self.test))"
    }
}

var aSubMain = SubMain(name: "Fred", test: SubMain.Test(number1: 1, number2: 2))

print("aSubMain before changing it's .test = \(aSubMain)")

aSubMain.test = SubMain.Test(number1: 7, number2: 4)
print("aSubMain after changing its .test property = \(aSubMain)")

let aSubMainTest = SubMain.Test(number1: 12, number2: 37)
print("aSubMainTest = \(aSubMainTest)")

(With a nod to Joakim, who posted a similar answer before I did.)

That outputs:

aSubMain before changing it's .test = SubMain(name: Fred, test = Test(number1: 1, number2: 2))
aSubMain after changing its .test property = SubMain(name: Fred, test = Test(number1: 7, number2: 4))
aSubMainTest = Test(number1: 12, number2: 37)
  • Related