사용자 정의 클래스에서 클러스터 스
-
21-12-2019 - |
문제
이것은 상대적으로 일반적인 디자인 패턴:
https://stackoverflow.com/a/17015041/743957
그것은 당신을 반환 서브 클래스에서 당신의 init
호출합니다.
하려고 해요 최고의 방법을 달성하기 같은 것을 사용하여 신속합니다.
내가 알고있는것은 매우 가능성이 있다는 것을 더 나은 방법을 달성하기 같은 것으로 신속합니다.그러나 내가에 의해 초기화될 기존 Obj-C 라이브러리는 나는 없다.그래서 그것은 필요가 이러한 방식으로 작동하고 호출할 수 있어서 Obj-C.
어떤 포인터는 것이 매우 감사합니다.
해결책
나는 그것을 믿지 않는 이유한 패턴을 가지고 있다는 사실 직접 지원에 신속하기 때문에,initialisers 값을 반환하지 않습으로 그들은 목 C-하지 않도록 할 수있는 기회를 얻을 반환하는 다른 객체를 인스턴스입니다.
형식을 사용할 수 있습 방법 개체로 공장이 상당히 인위적인 예입니다-
class Vehicle
{
var wheels: Int? {
get {
return nil
}
}
class func vehicleFactory(wheels:Int) -> Vehicle
{
var retVal:Vehicle
if (wheels == 4) {
retVal=Car()
}
else if (wheels == 18) {
retVal=Truck()
}
else {
retVal=Vehicle()
}
return retVal
}
}
class Car:Vehicle
{
override var wheels: Int {
get {
return 4
}
}
}
class Truck:Vehicle
{
override var wheels: Int {
get {
return 18
}
}
}
습니다.스
let c=Vehicle.vehicleFactory(4) // c is a Car
println(c.wheels) // outputs 4
let t=Vehicle.vehicleFactory(18) // t is a truck
println(t.wheels) // outputs 18
다른 팁
는"구라"의 방법을 만들기 클래스는 클러스터에는 실제로 이러한 프로토콜 대신의 기본 클래스입니다.
분명히 컴파일러에서 금지하는 정적 기능에 프로토콜 또는 프로토콜을 확장자.
까지 예: https://github.com/apple/swift-evolution/pull/247 (공장의 이니셜라이저)받아들이 구현,유일한 방법은 찾을 수 있는 이렇게 하려면 다음과 같다:
import Foundation
protocol Building {
func numberOfFloors() -> Int
}
func createBuilding(numberOfFloors numFloors: Int) -> Building? {
switch numFloors {
case 1...4:
return SmallBuilding(numberOfFloors: numFloors)
case 5...20:
return BigBuilding(numberOfFloors: numFloors)
case 21...200:
return SkyScraper(numberOfFloors: numFloors)
default:
return nil
}
}
private class BaseBuilding: Building {
let numFloors: Int
init(numberOfFloors:Int) {
self.numFloors = numberOfFloors
}
func numberOfFloors() -> Int {
return self.numFloors
}
}
private class SmallBuilding: BaseBuilding {
}
private class BigBuilding: BaseBuilding {
}
private class SkyScraper: BaseBuilding {
}
.
// this sadly does not work as static functions are not allowed on protocols.
//let skyscraper = Building.create(numberOfFloors: 200)
//let bigBuilding = Building.create(numberOfFloors: 15)
//let smallBuilding = Building.create(numberOfFloors: 2)
// Workaround:
let skyscraper = createBuilding(numberOfFloors: 200)
let bigBuilding = createBuilding(numberOfFloors: 15)
let smallBuilding = createBuilding(numberOfFloors: 2)
이 init()
지 않는 반환 값 -init
는 목 C 를 사용하여,공장 방법은 다음과 같 가장 쉬운 방법입니다.
하나의 트릭을 표시하는 것입니다 당신의 이니셜라이저로 private
, 은 다음과 같습니다.
class Person : CustomStringConvertible {
static func person(age: UInt) -> Person {
if age < 18 {
return ChildPerson(age)
}
else {
return AdultPerson(age)
}
}
let age: UInt
var description: String { return "" }
private init(_ age: UInt) {
self.age = age
}
}
extension Person {
class ChildPerson : Person {
let toyCount: UInt
private override init(_ age: UInt) {
self.toyCount = 5
super.init(age)
}
override var description: String {
return "\(self.dynamicType): I'm \(age). I have \(toyCount) toys!"
}
}
class AdultPerson : Person {
let beerCount: UInt
private override init(_ age: UInt) {
self.beerCount = 99
super.init(age)
}
override var description: String {
return "\(self.dynamicType): I'm \(age). I have \(beerCount) beers!"
}
}
}
이 결과는 다음과 같은 문제가 발생합니다.
Person.person(10) // "ChildPerson: I'm 10. I have 5 toys!"
Person.person(35) // "AdultPerson: I'm 35. I have 99 beers!"
Person(35) // 'Person' cannot be constructed because it has no accessible initializers
Person.ChildPerson(35) // 'Person.ChildPerson' cannot be constructed because it has no accessible initializers
그것은 아주 좋은 목적이 C 이후 private
수단,모든 서브 클래스에서 구현되어야 합 같이 소스 파일이 있는 사소한 차이는 구문 Person.person(x)
(나 Person.create(x)
또 무엇이든)신의 단순히 Person(x)
, 지만,실제적으로 말하면,그것은 동일합니다.
할 수 있을 그대로를 인스턴스화 Person(x)
, 수 차례 Person
으로는 프록시 등을 포함하는 개인스턴스의 실제 기본 클래스고 앞으로 모든 것을니다.없이 메시지 전달,이 작품에 대한 간단한 인터페이스와 함께 몇 가지 특성/법만 다루기 위해 더 복잡:P
내가 생각하는 실제로 클러스터의 패턴을 구현할 수 있습에서 신속을 사용하여 런타임 기능이 있다.주요 포인트이 대체하는 등의 새로운 객체와 함께 하위 클래스 경우를 초기화하고 있습니다.아래의 코드를 작동 하지만 나는 생각이 더 많은 관심 지불해야 하위 클래스'초기 설정입니다.
class MyClass
{
var name: String?
convenience init(type: Int)
{
self.init()
var subclass: AnyClass?
if type == 1
{
subclass = MySubclass1.self
}
else if type == 2
{
subclass = MySubclass2.self
}
object_setClass(self, subclass)
self.customInit()
}
func customInit()
{
// to be overridden
}
}
class MySubclass1 : MyClass
{
override func customInit()
{
self.name = "instance of MySubclass1"
}
}
class MySubclass2 : MyClass
{
override func customInit()
{
self.name = "instance of MySubclass2"
}
}
let myObject1 = MyClass(type: 1)
let myObject2 = MyClass(type: 2)
println(myObject1.name)
println(myObject2.name)