Reputation: 2184
struct MyRect : CGRect {...}
Is it possible at all in swift to subclass a Structure?
I have already found out on Apple official website an example: This example extends the CGRect structure to contain a computed area property:
extension CGRect {
var area: CGFloat {
return width * height
}
}
let rect = CGRect(x: 0.0, y: 0.0, width: 10.0, height: 50.0)
let area = rect.area
How can i define a subclass of a structure ?
Upvotes: 22
Views: 36093
Reputation: 12385
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 getAmerican() -> 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.getAmerican()
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.
Upvotes: 9
Reputation: 4351
It is not possible to subclass a struct
in Swift, only classes can be subclassed. An extension
is not a subclass, it's just adding additional functionality on to the existing struct
, this is comparable to a category in Objective-C.
Please see the Apple Swift documentation here to read about the differences between struct
and class
.
Upvotes: 37
Reputation: 71
This is a bit old, but I ran across it and thought I'd post a common pattern I use when needed. For example, an Application I was working on had the need to do some work with AspectRatios. Well, in my mind, an AspectRatio is nothing more than a CGSize with some additional functionality. I wanted a little separation between an AspectRatio and a CGSize, so I created a TypeAlias and then created an extension of the TypeAlias.
Something like this:
public typealias AspectRatio = CGSize
public extension AspectRatio {
enum Orientation {
case landscape
case portrait
case square
}
static let square = AspectRatio(width: 1.0, height: 1.0)
static let standard = AspectRatio(width: 4.0, height: 3.0)
static let wideScreen = AspectRatio(width: 16.0, height: 9.0)
static let theater = AspectRatio(width: 21.0, height: 9.0)
static let imax = AspectRatio(width: 1.9, height: 1.0)
func aspectRatio(precision: Int? = nil) -> CGFloat {
let aspectRatio = width / height
guard let precision = precision else {
return aspectRatio
}
let multiplier = pow(10, Double(precision))
let value = (Double(aspectRatio) * multiplier).rounded() / multiplier
return CGFloat(value)
}
var orientation: Orientation {
switch self.aspectRatio() {
case let aspect where aspect > 1.0:
return .landscape
case let aspect where aspect < 1.0:
return .portrait
default:
return .square
}
}
func flipped() -> AspectRatio {
return AspectRatio(width: height, height: width)
}
...
}
Then I could easily define variables like such:
var aspectRatio: AspectRatio = .imax
Upvotes: 2
Reputation: 938
Since Swift 5.1 it is now possible to do something similar to what you asked for: using composition, with KeyPath
and dynamicMemberLookup
. Have a look: https://medium.com/@acecilia/struct-composition-using-keypath-and-dynamicmemberlookup-kind-of-struct-subclassing-but-better-6ce561768612?source=friends_link&sk=da479578032c0b46c1c69111dfb6054e
Upvotes: 2