Alternate approach to inheritance for Swift structs?
In Swift with struct you can create protocol
for common task and also implement default implementation using protocol extension.
protocol Vehicle {
var model: String { get set }
var color: String { get set }
}
//Common Implementation using protocol extension
extension Vehicle {
static func parseVehicleFields(jsonDict: [String:Any]) -> (String, String) {
let model = jsonDict["model"] as! String
let color = jsonDict["color"] as! String
return (model, color)
}
}
struct Car : Vehicle {
var model:String
var color:String
let horsepower: Double
let license_plate: String
init(jsonDict: [String:Any]) {
(model, color) = Car.parseVehicleFields(jsonDict: jsonDict)
horsepower = jsonDict["horsepower"] as! Double
license_plate = jsonDict["license_plate"] as! String
}
}
struct Bicycle : Vehicle {
var model:String
var color:String
let chainrings: Int
let sprockets: Int
init(jsonDict: [String:Any]) {
(model, color) = Bicycle.parseVehicleFields(jsonDict: jsonDict)
chainrings = jsonDict["chainrings"] as! Int
sprockets = jsonDict["sprockets"] as! Int
}
}
Swift Struct idiom to replace OOP Type Inheritance Pattern?
You should be able to accomplish this with protocols. You would move the common logic into a Protocol and then create two classes that would conform to this protocol with different initializers. Then where you would refer to a particular object type, you could refer to the protocol instead.
protocol RectangleProtocol {
var left:Int {get}
var right:Int {get}
var top:Int {get}
var bottom:Int {get}
}
struct Rectangle: RectangleProtocol {
let left: Int
let right: Int
let top: Int
let bottom: Int
init(leftValue:Int, rightValue:Int, topValue:Int, bottomValue:Int) {
self.left = leftValue
self.right = rightValue
self.top = topValue
self.bottom = bottomValue
}
}
struct RationalRectangle: RectangleProtocol {
let left: Int
let right: Int
let top: Int
let bottom: Int
init(leftValue:Int, rightValue:Int, topValue:Int, bottomValue:Int) {
self.left = min(leftValue, rightValue)
self.right = max(leftValue, rightValue)
self.top = min(topValue, bottomValue)
self.bottom = max(topValue, bottomValue)
}
}
let rectangle: RectangleProtocol = Rectangle(leftValue: 4, rightValue 4, topValue: 8, bottomValue: 8)
let rationalRectangle: RectangleProtocol = RationalRectangle(leftValue: 4, rightValue:8, topValue: 7, bottomValue: 4)
// Now both of these represent a struct that conforms to the RectangleProtocol.
How do I subclass a struct in Swift?
You cannot subclass structures in Swift but you can, in some sense, mimic subclassing by creating a structure that simply vends out the structure that you wish to subclass. For example, if you wanted to subclass Calendar
(a structure), you could create a structure that returns configured calendars.
struct WorldCalendar {
let american1: Calendar = {
var c = Calendar(identifier: .gregorian)
c.timeZone = .current
c.locale = Locale(identifier: "en_US_POSIX")
return c
}()
static let american2: Calendar = {
var c = Calendar(identifier: .gregorian)
c.timeZone = .current
c.locale = Locale(identifier: "en_US_POSIX")
return c
}()
static func american3() -> Calendar {
var c = Calendar(identifier: .gregorian)
c.timeZone = .current
c.locale = Locale(identifier: "en_US_POSIX")
return c
}
}
let worldCalendar = WorldCalendar()
let cal1 = worldCalendar.american1
let cal2 = WorldCalendar.american2
let cal3 = WorldCalendar.american3()
How you vend the configured structures (as an instance property, a static property, a static function, etc.) is just a matter of what better fits into your application and, frankly, personal preference.
Inherit from struct
A struct Is Implicitly Sealed
According to this link:
Every struct in C#, whether it is user-defined or defined in the .NET Framework, is sealed–meaning that you can’t inherit from it. A struct is sealed because it is a value type and all value types are sealed.
A struct can implement an interface, so it’s possible to see another type name following a colon, after the name of the struct.
In the example below, we get a compile-time error when we try to define a new struct that inherits from the one defined above.
public struct PersonName
{
public PersonName(string first, string last)
{
First = first;
Last = last;
}
public string First;
public string Last;
}
// Error at compile time: Type 'PersonName' in interface list is not an interface
public struct AngryPersonName : PersonName
{
public string AngryNickname;
}
How to prevent subclasses from inheriting super class's static method in Swift?
The comments of my question contains many good answers:
there is no dedicated swift feature to prevent subclasses from inheriting super class static methods.
move static functions to a new (final) class or struct
use
class
instead ofstatic (=final class)
and override the class method and add@available(*, unavailable)
to it.use Lint tools
I think the easiest way is to create a new (final) class for static methods which do not depend on subclasses, though, that sacrifices code completion feature a little.
I hope someday Swift will introduce @noInherit static func
attribute.
EDIT
I found another way to restrict the way to call a static method in runtime:
class Base {
static func f() {
if Self.self != Base.self {
fatalError("don't call from subclass: " + String(describing: Self.self))
}
print("hello world")
}
}
note: The disadvantage of the EDIT is that it is checked only in runtime. The benefit of it is that you need only 3 lines and you don't need to override the static method in all subclasses. But this way should be used only when you have confident that checking in runtime is enough and safe for your app.
Related Topics
How to Concatenate Optional Swift Strings
Convert Timestamp String with Epochal Time and Timezone into Nsdate
How to Use .Svg Images in Swiftui
Convert Float Value to String in Swift
How to Setup a Second Component with a Uipickerview
Realm Mobile Platform, How to Connect While Offline
How to Get Next Case of Enum(I.E. Write a Circulating Method) in Swift 4.2
How to Enumerate a Slice Using the Original Indices
Swiftui: Navigation Bar Title in Reusable Cross-Platform (iOS & MACos) View
How to Have a Swift Protocol Without Functions
Core Data: Could Not Cast Value of Type 'Mytype_Mytype_2' to Mytype
Firebase Query Containing Value
Open a Viewcontroller from Remote Notification
Not Condition in 'If Case' Statement
Getting Path for Resource in Command Line Tool
How to View Value of Swift "Let" Constant in Xcode 6 Debugger