Should I use optional for properties of object models that will be parsed from JSON? - ios

My iOS app has a pretty common setup: it makes HTTP queries to an API server that responds with JSON objects. These JSON objects are then parsed to appropriate Swift objects.
Initially I divided properties into required properties and optional properties, mostly based on my API server's database requirements. For example, id, email, and name are require fields so they use non-optional types. Others can be NULL in database, so they are optional types.
class User {
let id: Int
let email: String
let profile: String?
let name: String
let motive: String?
let address: String?
let profilePhotoUrl: String?
}
Recently, I started wondering whether this was a good setup at all. I found out that although some properties might be always in the database, that does not mean that those properties will always be included in the JSON response.
For example, in the User profile page, all these fields are needed to properly display the view. Therefore, JSON response will include all these fields. For a view that lists users' names, however, I would not need email or id, and JSON response should probably not include those properties either. Unfortunately, this will cause error and crash the app when parsing JSON response into Swift object since the app expects id, email, name to be always not-nil.
I'm thinking of changing all properties of Swift objects into optionals, but it feels like throwing away all the benefits of this language-specific feature. Moreover, I will have to write many more lines of code to unwrap all these optionals somewhere else in the app anyway.
On the other hand, JSON objects are by their nature not very interoperable with strict static typing and nil-checking of Swift so it might be better to simply accept that annoyance.
Should I transition to models with every property as optionals? Or is there a better way? I'd appreciate any comment here.

There are three ways you can go with this:
Always send all the JSON data, and leave your properties non-optional.
Make all the properties optional.
Make all the properties non-optional, and write your own init(from:) method to assign default values to missing values, as described in this answer.
All of these should work; which one is "best" is opinion-based, and thus out of the scope of a Stack Overflow answer. Choose whichever one is most convenient for your particular need.

The first thing to do is ask: Does an element of the “view that lists users' names” need to be the same kind of object as the model object behind a “User profile page”? Perhaps not. Maybe you should create a model specifically for the user list:
struct UserList: Decodable {
struct Item: Decodable {
var id: Int
var name: String
}
var items: [Item]
}
(Although the question said the JSON response might not include id, it doesn't seem like a user list without ids with be particularly useful, so I made it required here.)
If you really want them to be the same kind of object, then maybe you want to model a user as having core properties that the server always sends, and a “details” field that might be nil:
class User: Decodable {
let id: Int
let name: String
let details: Details?
struct Details: Decodable {
var email: String
var profile: String?
var motive: String?
var address: String?
var profilePhotoUrl: String?
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(Int.self, forKey: .id)
name = try container.decode(String.self, forKey: .name)
details = container.contains(.email) ? try Details(from: decoder) : nil
}
enum CodingKeys: String, CodingKey {
case id
case name
case email // Used to detect presence of Details
}
}
Note that I create the Details, if it's present, using Details(from: decoder), instead of the usual container.decode(Details.self, forKey: .details). I do it using Details(from: decoder) so that the properties of the Details come out of the same JSON object as the properties of the User, instead of requiring a nested object.

The premise:
Partial representing is a common pattern in REST. Does that mean all
properties in Swift need to be optionals? For example, the client
might just need a list of user ids for a view. Does that mean that all
the other properties (name, email, etc) need to be marked as optional?
Is this good practice in Swift?
Marking properties optional in a model only indicates that the key may or may not come. It allows the reader to know certain things about the model in the first look itself.
If you maintain only one common model for different API response structures and make all the properties optional, whether that's good practice or not is very debatable.
I have done this and it bites. Sometimes it's fine, sometimes it's just not clear enough.
Keeping one model for multiple APIs is like designing one ViewController with many UI elements and depending on particular cases, determining what UI element should be shown or not.
This increases the learning curve for new developers as there's more understanding-the-system involved.
My 2 cents on this:
Assuming we are going ahead with Swift's Codable for encoding/decoding models, I would break it up into separate models rather than maintaining a common model with all optionals &/or default values.
Reasons for my decision are:
Clarity of Separation
Each model for a specific purpose
Scope of cleaner custom decoders
Useful when the json structure needs a little pre-processing
Consideration of API specific additional keys that might come later on.
What if this User list API is the only one requiring more keys like, say, number of friends or some other statistic?
Should I continue to load a single model to support different cases with additional keys that come in only one API response but not another?
What if a 3rd API is designed to get user information but this time with a slightly different purpose? Should I over-load the same model with yet more keys?
With a single model, as the project continues to progress, things could get messy as key availability in now very API-case-based. With all being optionals we will have alot of optional bindings & maybe some shortcut nil coalescings here and there which we could have avoided with dedicated models in the first place.
Writing up a model is cheap but maintaining cases is not.
However, if I was lazy and I have a strong feeling crazy changes aren't coming up ahead, I would just go ahead making all the keys optionals and bear the associated costs.

I typically make all non-critical properties optional, and then have a failable initializer. This allows me to better handle any changes in the JSON format or broken API contracts.
For example:
class User {
let id: Int
let email: String
var profile: String?
var name: String?
var motive: String?
var address: String?
var profilePhotoUrl: String?
}
This means that I will never have a user object without an id or email (let's assume those are the two that always need to be associated with a user). If I get a JSON payload without an id or email, the Initializer in the User class will fail and won't create the user object. I then have error handling for failed initializers.
I'd much rather have a swift class with optional properties than a bunch of properties with an empty string value.

This really depends on the way you are handling your data. If you are handling your data through a "Codable" class, then you have to write a custom decoder to throw an exception when you don't get certain expected values. Like so:
class User: Codable {
let id: Int
let email: String
let profile: String?
let name: String
let motive: String?
let address: String?
let profilePhotoUrl: String?
//other methods (such as init, encoder, and decoder) need to be added below.
}
Because I know that I'm going to need to return an error if I don't get the minimum required parameters, you would need something like an Error enum:
enum UserCodableError: Error {
case missingNeededParameters
//and so on with more cases
}
You should be using coding keys to keep things consistent from the server. A way to do that inside of the User Object would be like so:
fileprivate enum CodingKeys: String, CodingKey {
case id = "YOUR JSON SERVER KEYS GO HERE"
case email
case profile
case name
case motive
case address
case profilePhotoUrl
}
Then, you need to write your Decoder. A way to do that would be like so:
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
guard let id = try? values.decode(Int.self, forKey: .id), let email = try? values.decode(String.self, forKey: .email), let name = try? values.decode(String.self, forKey: .name) else {
throw UserCodableError.missingNeededParameters
}
self.id = id
self.email = email
self.name = name
//now simply try to decode the optionals
self.profile = try? values.decode(String.self, forKey: .profile)
self.motive = try? values.decode(String.self, forKey: .motive)
self.address = try? values.decode(String.self, forKey: .address)
self.profilePhotoUrl = try? values.decode(String.self, forKey: .profilePhotoUrl)
}
SOMETHING TO NOTE: You should write your own encoder as well to stay consistent.
All of that can go, simply to a nice calling statement like this:
if let user = try? JSONDecoder().decode(User.self, from: jsonData) {
//do stuff with user
}
This is probably the safest, swift-ist, and most object oriented way to handle this type of issue.

I recommend to keep all non-scalar(String, Custom Types etc) properties as optional, scalar(Int, Float, Double etc) as non-optional(with some exceptions) by assigning a default value and collections with empty array. e.g,
class User {
var id: Int = 0
var name: String?
var friends: [User] = []
var settings: UserSettings?
}
This assures you a crash free app no matter what happens to server. I would prefer abnormal behavior over a crash.

If the server is giving Null value for the other properties, you can go for optionals and safe unwrap. Or while unwrapping you can assign empty string to property if the value is nil
profile = jsonValue ?? ""
Other case since the other properties are String data type you can assign default value as a empty string
class User {
let id: Int
let email: String
let profile: String = ""
let name: String
let motive: String = ""
let address: String = ""
let profilePhotoUrl: String = ""
}

Yes, you should use optional if the property is not necessary in API and if you want some value in the mandatory property then assign blank value:
class User {
let id: Int?
let email: String? = ""
let profile: String?
let name: String? = ""
let motive: String?
let address: String?
let profilePhotoUrl: String?
}

In my opinion, I will choose 1 of 2 solutions:
Edit my init func from JSON to object, init with default object values for all props (id = -1, email = ''), then read JSON with optional checking.
Create a new class/struct for that specific case.

I would prefer using failable Initializer its neat compared to other options.
So keep the required properties as non-optionals and create object only if they are present in the response (you can use if-let or gaurd-let to check this in response), else fail the creation of the object.
Using this approach we avoid making non-optionals as optionals and having a pain to handle them throughout the program.
Also optionals are not meant for defensive programming so don't abuse optionals by making "non-optional" properties as optionals.

I would prefer optional properties because you can not promise JSON values to be there all the time and any change on response property name would crash your app.
If you do not use optional values, you have to control parameters while parsing and add a default value if you want a crash free app. And you wouldn't know if it was nil or empty string from server.
Optional values is your best friends.
object mapper for mutable and non-mutable properties.
realm-swift for default non-optional values.

Related

Is it possible to force encode Date as Date type instead of string?

I am trying to mock Apollo Queries using its init. It pretty much is taking in a dictionary to build the object up.
public init(unsafeResultMap: [String: Any]) {
self.resultMap = unsafeResultMap
}
So, I have decided to create Mock objects that have the same properties of the query objects while being Encodable (So we get the free JSON conversion, which can be represented as a string version dictionary).
For example:
class MockAnimalObject: Encodable {
let teeth: MockTeethObject
init(teeth: MockTeethObject) {
self.teeth = teeth
}
}
class MockTeethObject: Encodable {
let numberOfTeeth: Int
let dateOfTeethCreation: Date
init (numberOfTeeth: Int, dateOfTeethCreation: Date) {
self.numberOfTeeth = numberOfTeeth
self.dateOfTeethCreation = dateOfTeethCreation
}
}
The problem is, the Apollo conversion checks the types during the result map, which in our case is a string of [String: Encodable].
And this is where the Date encodable becomes a problem.
/// This property is auto-generated and not feasible to be edited
/// Teeth date for these teeth
public var teethCreationDate: Date {
get {
// This is the problem. resultMap["teethCreationDate"] is never going to be a Date object since it is encoded.
return resultMap["teethCreationDate"]! as! Date
}
set {
resultMap.updateValue(newValue, forKey: "teethCreationDate")
}
}
So, I am wondering if it is possible to override the encoder to manually set the date value as a custom type.
var container = encoder.singleValueContainer()
try container.encode(date) as Date // Something where I force it to be a non-encodable object
JSON has nothing to do with this. JSON is not any kind of dictionary. It's a serialization format. But you don't want a serialization format. You want to convert types to an Apollo ResultMap, which is [String: Any?]. What you want is a "ResultMapEncoder," not a JSONEncoder.
That's definitely possible. It's just an obnoxious amount of code because Encoder is such a pain to conform to. My first pass is a bit over 600 lines. I could probably strip it down more and it's barely tested, so I don't know if this code works in all (or even most) cases, but it's a start and shows how you would attack this problem.
The starting point is the source code for JSONEncoder. Like sculpture, you start with a giant block of material, and keep removing everything that doesn't look like what you want. Again, this is very, very lightly tested. It basically does what you describe in your question, and not much else is tested.
let animal = MockAnimalObject(teeth: MockTeethObject(numberOfTeeth: 10,
dateOfTeethCreation: .now))
let result = try AnyEncoder().encode(animal)
print(result)
//["teeth": Optional(["dateOfTeethCreation": Optional(2022-08-12 18:35:27 +0000),
// "numberOfTeeth": Optional(10)])]
The key changes, and where you'd want to explore further to make this work the way you want, are:
Gets rid of all configuration and auto-conversions (like snake case)
Handles the "special cases" (Date, Decimal, [String: Encodable]) by just returning them. See wrapEncodable and wrapUntyped
If you want [String: Any] rather than [String: Any?] (which is what ResultMap is), then you can tweak the types a bit. The only tricky piece is you would need to store something like nil as Any? as Any in order to encode nil (or you could encode NSNull, or you could just not encode it at all if you wanted).
Note that this actually returns Any, since it can't know that the top level encodes an object. So you'll need to as? cast it to [String: Any?].
To your question about using Mirror, the good thing about Mirror is that the code is short. The bad thing is that mirror is very slow. So it depends on how important that is. Not everything has the mirror you expect, however. For your purposes, Date has a "struct-like" Mirror, so you have to special-case it. But it's not that hard to write the code. Something like this:
func resultMap(from object: Any) -> Any {
// First handle special cases that aren't what they seem
if object is Date || object is Decimal {
return object
}
let mirror = Mirror(reflecting: object)
switch mirror.displayStyle {
case .some(.struct), .some(.class), .some(.dictionary):
var keyValues: [String: Any] = [:]
for child in mirror.children {
if let label = child.label {
keyValues[label] = resultMap(from: child.value)
}
}
return keyValues
case .some(.collection):
var values: [Any] = []
for child in mirror.children {
values.append(resultMap(from: child.value))
}
return values
default:
return object
}
}
let animal = MockAnimalObject(teeth: MockTeethObject(numberOfTeeth: 10, dateOfTeethCreation: .now))
let result = resultMap(from: animal)
print(result)
// ["teeth": ["dateOfTeethCreation": 2022-08-12 21:08:11 +0000, "numberOfTeeth": 10]]
This time I didn't bother with Any?, but you could probably expand it that way if you needed. You'd need to decide what you'd want to do about enums, tuples, and anything else you'd want to handle specially, but it's pretty flexible. Just slow.
As pointed out in comments, JSON (Javascript object notation) is universal format and is not anyhow related to Date object in Swift after it is encoded. Therefore somewhere in the flow you need to make it String Double or some other object type that can be encoded to JSON. Anyway, if you want to make encoding Date to be easier you can take hold of some native JSONEncoder functions, such as folowing:
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601

Unclear use of Storage

How do I use Storage in Vapor 4?
I tried the following:
if let someValue = req.storage.get(theKey) as? String {
// do something
} else {
req.storage.set(theKey, to: "Some Value")
}
However I get the following Errors:
error: type of expression is ambiguous without more context
if let original: String = req.storage.get(theKey) {
~~~~~~~~~~~~^~~~~~~~~~~
error: type of expression is ambiguous without more context
req.storage.set(theKey, to: "Some Value")
~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I also did not find any documentation on this topic.
The input key is actually a Protocol use must implement. If you want to see examples of how Store is used, do like #imike says and look for usages of the Storage class.
Storage is not string based key object storage. You have to declare a struct conforming to StorageKey, implement the typealias Value representing the object type you want to store.
If you need to store a string let's take this example :
struct MyStringKey: StorageKey {
typealias Value = String
}
...
request.storage.set(MyStringKey.self, to: "my string")
var myString: String? = request.storage.get(MyStringKey.self)
It is NOT possible for the Key to be any arbitrary String. The key must be predefined.

How can one use Swift's Decodable to parse an arbitrary JSON string where you only know or care about a few fields? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
The new Swift "Decoder" class sounds like a great way to parse JSON data, but all of the examples I've found use a well-known, well-defined 'struct' to do so.
In my case I'm querying an arbitrary website that returns a HUGE JSON string and I only care about a few of the (deeply nested) fields, so I don't want to take all that time to define a 'struct' to get at them.
Is it even possible to do this with "Decoder"? And if so, how does one go about it?
The question seems to be based on a misapprehension about how Decodable works. As a convenience, Decodable is willing to do some automatic code generation behind the scenes so that you can define a struct or nest of structs and just decode the entirety of the JSON. But you are not required to take advantage of that in order to decode JSON.
There is no need to define struct properties for "fields" you don't care about. If a JSON dictionary contains 100 keys and your corresponding struct contains just one property, no problem; that key will be fetched, and no others.
With regard to the "deeply nested" part, it should not take you much time to write simple nested structs that perform the dive to reach the dictionary you really care about. But if you don't want to do even that, you could write an implementation of init(from:) that dives down and fetches out the desired values.
In other words, if you think of Decodable as consisting primarily of your implementation of init(from:), and learn to write the code that it needs, you will see that this JSON can be parsed in a few quick simple lines of code.
As an example, here's a JSON sketch of a deeply nested piece of information with a bunch of extra information at every level that we want to ignore:
{
"ignore": true,
"outer1": {
"ignore": true,
"outer2": {
"ignore": true,
"outer3": {
"name": "matt",
"ignore": true
}
}
}
}
What I'd like to do is define a very simple struct Person that consists solely of the deeply nested name:
struct Person : Decodable {
let name : String
}
I can do that! To do so, I implement Decodable myself, supplying a "hoover" CodingKey adopter struct and an implementation of init(from:), like this (this may look like a lot of work, but it isn't, because the AnyCodingKey implementation is boilerplate, copied and pasted from here, and the init(coder:) implementation is just a few lines of code that were easy to write):
struct Person : Decodable {
let name : String
struct AnyCodingKey : CodingKey {
var stringValue: String
var intValue: Int?
init(_ codingKey: CodingKey) {
self.stringValue = codingKey.stringValue
self.intValue = codingKey.intValue
}
init(stringValue: String) {
self.stringValue = stringValue
self.intValue = nil
}
init(intValue: Int) {
self.stringValue = String(intValue)
self.intValue = intValue
}
}
init(from decoder: Decoder) throws {
var con = try! decoder.container(keyedBy: AnyCodingKey.self)
con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"outer1"))
con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"outer2"))
con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"outer3"))
let name = try! con.decode(String.self, forKey: AnyCodingKey(stringValue:"name"))
self.name = name
}
}
When I want to dive into the JSON and grab the name information, it's trivial:
let person = try! JSONDecoder().decode(Person.self, from: json)
The result is a Person object with name value "matt". Note that I didn't have to add any of the ignore keys and I didn't need to make a nest of structs.
Sure you can achieve this but with both JSonSerialization & Decodable , you have to serialize the json until reach the desired content then decode it ,but instead I recommend to create structs for root keys only then decode , think of it as it's a path from top to bottom don't decode a key that isn't in the path of your desired content

Populate List in Swift 2.0 and display results

I've been learning iOS development for the past three weeks, I'm currently following a course on Udemy so far so good.
However I'm following one of the lectures whereby we build an Instagram Clone.
The instructor is using three arrays which are as follows:
var usernames = [""] // Stores all usernames
var userIds = [""] // Stores all Id's of the given usernames
var isFollowing = [false] // Stores where or not you're following that user
To me trying to keep track of what userId goes with what username using two arrays is basically an accident waiting to happen so I decided to set off and find a more feasible approach. I reverted back to my .Net days and decided to create a list so I went and created a class as follows:
class Users{
var Username : NSString = ""
var UserId : NSString = ""
var Following : Bool = false
}
Now inside my ViewController I make a call to Parse which returns me a list of users and I'm basically trying to loop through the response, and add them to the list class as shown here:
var t = [Users]() // After googling the web, this seems to be the syntax for a list declaration ?
let u = Users()
for object in users{
if let o = object as? PFUser {
u.Username = o.username!
u.UserId = o.objectId!
u.Following = o.IsFollowing!
self.t.append(u)
}
}
print(self.t)
Now when I print this to the console I see the following:
ParseStarterProject_Swift.Users
As I have one user at present, however when I try to loop through T and display the username in the console it doesn't display anything.
for x in t {
print(x.Username)
}
Your basic intuition is correct, it's better to have an array of custom objects, not multiple arrays.
Regarding making it more Swifty, consider your Users type. You might want something like:
struct User {
let username: String
let userId: String
let following: Bool
}
Note,
property names should start with lowercase letter;
Users should probably be called User, as it represents a single user;
we don't generally initialize values to default values like that, but rather specify them in the initializer;
we probably use String not NSString;
if a property cannot change, you'd use let, not var;
properties begin with lower case letters;
Then you can do something like:
var t = [User]()
for object in users {
if let o = object as? PFUser {
t.append(User(username: o.username!, userId: o.objectId!, following: o.IsFollowing!)
}
}
print(t)
Clearly, with all of those ! forced unwrapping operators, you'd want to be confident that those fields were populated for all of those properties.
Using struct is nice because (a) it's a value type; (b) you get the initializer for free; and (c) you can just print them. If you really wanted User to be a reference type (a class), you'd do something like:
class User {
let username: String
let userId: String
let following: Bool
init(username: String, userId: String, following: Bool) {
self.username = username
self.userId = userId
self.following = following
}
}
And if you wanted to be able to just print them, you'd define it to conform to CustomStringConvertible:
extension User: CustomStringConvertible {
var description: String { return "<User; username = \(username); userId = \(userId); following = \(following)>" }
}
With the class, you can feel free to change that description computed property to show it in whatever format you want, but it illustrates the idea.
You are correct in considering that keeping track of what userId goes with what username using two arrays is dangerous, you in the correct direction with your approach.
First, I would just like to suggest that you use correct naming convention:
Classes should be singular (except in very specific cases).
Variable/property names should begin with lowercase.
This would mean that your user class should look like this:
class User {
var username : NSString = ""
var userId : NSString = ""
var following : Bool = false
}
I will keep your existing naming use for the next part. The main problem with your code is that the variable "u" is a object which you create only once and then modify it. You should be creating a new "Users" object for each user instead of modifying the original. If you don't do this you will just have an array with the same user multiple times. This is how your code would look now:
var t = [Users]()
for object in users {
if let o = object as? PFUser {
let u = Users()
u.Username = o.username!
u.UserId = o.objectId!
u.Following = o.IsFollowing!
self.t.append(u)
}
}
print(self.t)
Next you mention that when you print to console you see the text: ParseStarterProject_Swift.Users, that is because Swift does not automatically print a pretty text with the content of your object. In order for it to print something more detailed, your "Users" object would need to implement the CustomStringConvertible. You can see a more detailed answer about that here: how-can-i-change-the-textual-representation-displayed-for-a-type-in-swif.
Lastly, you mention that when you loop trough "t" and display the username in the console it does not display anything. This is caused by one of two things:
Because there are no users being returned from parse, so the "t" array is actually empty. Try print(t.count) to see how many objects are in the array.
Because your "Users" object declares an empty string "" as the default username and the username is not being set correctly when getting the data from the parse. Which means that it IS actually printing something, just that it is an empty string. Try defining a different default value like var username : NSString = "Undefined" to see if it prints something.
Good luck learning swift!

Subclassing v.s. Protocols

Lets begin with the Class approach:
class LoginCredentials {
var id : String
init(userID:String) {
self.id = userID
}
}
then we will have the following:
class FacebookLoginCredentials : LoginCredentials {
var token : String
init(userID:String,userToken:String) {
self.token = userToken
super.init(userID: userID)
}}
And
class TwitterLoginCredentials : LoginCredentials {
var token : String
var secret : String
init(userID:String,userToken:String,secret : String) {
self.token = userToken
self.secret = secret
super.init(userID: userID)
}
}
The second Approach is the Protocol Oriented if I am not wrong
protocol LoginCredentials {
var id : String { get }
}
then we will have :
struct FacebookLoginCredentials : LoginCredentials {
var id: String
var token : String
init(userID:String,userToken:String) {
self.id = userID
self.token = userToken
}
}
And
struct TwitterLoginProfile : LoginCredentials {
var id: String
var token : String
var secret : String
init(userID:String,userToken:String,secret : String) {
self.token = userToken
self.secret = secret
self.id = userID
}
}
I just need to know which one is more Swift ?
Ultimately, neither of these approaches is "more Swift". In Swift, you will sometimes want to use inheritance and other times you will want to use protocols. The real decision point for these two approaches is:
Do you want value type semantics (structs and protocols) or do you want reference type semantics (classes and protocols). I usually default to value type semantics because they are safer but there are definitely circumstances where reference type semantics are important. You can read more about that here: Why Choose Struct over Class.
Either or is acceptable in swift.
Here is how you want to distinguish from the two.
When working with Protocols, you want to treat these as if they were blue prints for your objects.
Ballplayers must know what a ball is, so any person that wants to be a Ballplayer must know what a ball is.
You have a set of rules you want certain objects to follow, make a protocol.
If you want to make objects that have functionality, and you want the children to inherent this functionality, and then have more functionality, then do the inheret class structure.
Dad can throw a ball at 100MPH
Junior can throw a ball at 100MPH and throw a curve ball.
This would be done with a class, not protocol
Structure instances are always passed by value, and class instances are always passed by reference. This means that they are suited to different kinds of tasks. As you consider the data constructs and functionality that you need for a project, decide whether each data construct should be defined as a class or as a structure.
As a general guideline, consider creating a structure when one or more of these conditions apply:
The structure’s primary purpose is to encapsulate a few relatively simple data values.
It is reasonable to expect that the encapsulated values will be copied rather than referenced when you assign or pass around an instance of that structure.
Any properties stored by the structure are themselves value types, which would also be expected to be copied rather than referenced.
The structure does not need to inherit properties or behavior from another existing type.
Examples of good candidates for structures include:
The size of a geometric shape, perhaps encapsulating a width property and a height property, both of type Double.
A way to refer to ranges within a series, perhaps encapsulating a start property and a length property, both of type Int.
A point in a 3D coordinate system, perhaps encapsulating x, y and z properties, each of type Double.
In all other cases, define a class, and create instances of that class
to be managed and passed by reference. In practice, this means that
most custom data constructs should be classes, not structures.
Why Choose Struct Over Class?

Resources