I'm trying to subclass a nested class as follows:
import Foundation
class Blah {
class BlahNested {
func name() -> String {
return "Blah"
}
}
var blah_ : BlahNested
init() {
blah_ = Blah.BlahNested()
}
func name() -> String {
return blah_.name()
}
}
class SubBlah : Blah {
class BlahNested : Blah.BlahNested {
override func name() -> String {
return "SubBlah"
}
}
init() {
super.init()
blah_ = SubBlah.BlahNested() // THIS LINE IS HAVING ISSUES
}
}
It seems that that nested subclass having the same name as the parent (i.e., "BlahNested" being the same in both the parent and the child) is causing issues. Is it required to have different names in such a case? Thanks!
Related
In Swift, I want to make my base class static method return its subclass objects when the static method is called from a subclass.
When returning one subclass object, I can make it possible by using init().
But when returning multiple subclass objects, init() can not be used.
And I want to not only just return subclass objects from the parent static method, but also to implement some logic other than instantiation in the parent static method, and make the static method of each subclass inherit the parent's static method behavior.
I have 3 sub-classes. So, I don't want to write the same code in the static methods of 3 sub-classes.
How should I do?
If possible, I want to use the static method instead of init() to return a single subclass object, too.
class Base {
func f() {
print("base class")
}
// this does not works. it creates a base class object.
static func createSubclassObject() -> Base {
return Base()
}
// this works. it creates a subclass object.
init() {
}
// this does not work. base class objects are created.
static func createSubclassObjects(count: Int) -> [Base] {
var objects = [Base]()
for _ in 0 ..< count {
objects.append(Base())
}
return objects
}
/* probably I need something like this. but this code generates a compile error
static func createSubclassObjects(count: Int) -> [Self] {
var objects = [Self]()
for _ in 0 ..< count {
objects.append(Self())
}
return objects
}
*/
// generic also does not work. this returns a base class object.
static func createSubclassObjectByGeneric<T: Base>() -> T {
return T()
}
}
class Sub: Base {
override func f() {
print("sub class")
}
}
print(Sub().f())
// sub class・
print(Sub.createSubclassObject().f())
// base class
Sub.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// base class
// base class
print(Sub.createSubclassObjectByGeneric().f())
// base class
You need to return Self, not Base.
static func createSubclassObject() -> Self {
.init()
}
required init() { }
Also, don't use a for loop. There is an array initializer premade for what you're doing.
static func createSubclassObjects(count: Int) -> [Base] {
.init(repeating: createSubclassObject(), count: count)
}
The following code works. But I think there should be better solutions because I don't want to define class func sub() in the parent class and override class func sub() in each sub class.
EDIT: See the Jessy's answer, which is the better solution.
class Base {
func f() {
print("base class")
}
static func createSubclassObjects(count: Int) -> [Base] {
var objects = [Base]()
for _ in 0 ..< count {
//objects.append(Base())
objects.append(Self.sub())
}
return objects
}
class func sub() -> Base {
Base()
// or use fatalError() if you don't need to call createSubclassObjects(count: Int) from the base class
}
}
class Sub1: Base {
override func f() {
print("sub1 class")
}
override class func sub() -> Base {
Sub1()
}
}
class Sub2: Base {
override func f() {
print("sub2 class")
}
override class func sub() -> Base {
Sub2()
}
}
Base.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// base class
// base class
Sub1.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// sub1 class
// sub1 class
Sub2.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// sub2 class
// sub2 class
Consider the following example
class ClassA {
func createAnInstanceOfAnotherClass() -> AnotherClass {
return AnotherClass()
}
func callMeA() {
}
}
class ClassB {
func createAnInstanceOfAnotherClass() -> AnotherClass {
return AnotherClass()
}
func callMeB() {
}
}
class AnotherClass {
func doSomethingAndReturn() {
return
}
}
class MethodChain {
func methodChainTest() {
ClassA()
.createAnInstanceOfAnotherClass()
.doSomethingAndReturn() //return to ClassA
.callMeA() // call classA callMe
ClassB()
.createAnInstanceOfAnotherClass()
.doSomethingAndReturn() // return to ClassB
.callMeB() // call ClassB callMe
}
}
Is it possible for the class AnotherClass to return the instance of the class that created it?
In this example I want to use the class method doSomethingAndReturn when method chaining with both ClassA and ClassB and then contione the method chain with methods from either ClassA or ClassB
You could make AnotherClass generic with a type parameter Creator, which stores the type of its creator.
class ClassA {
func createAnInstanceOfAnotherClass() -> AnotherClass<ClassA> {
return AnotherClass(creator: self)
}
func callMeA() {
}
}
class ClassB {
func createAnInstanceOfAnotherClass() -> AnotherClass<ClassB> {
return AnotherClass(creator: self)
}
func callMeB() {
}
}
class AnotherClass<Creator: AnyObject> {
// weak to avoid retain cycles!
private weak var creator: Creator?
init(creator: Creator) {
self.creator = creator
}
func doSomethingAndReturn() -> Creator {
// assuming you always do method chaining,
// and not do something weird with the intermediate results,
// this should be safe to unwrap forcefully
creator!
}
}
I would like to override a method that is declared in a framework and implemented in an extension.
Here's what I've tried :
import UIKit
// Code from a dependency
class Object { // UIViewController
func printSomething() {
print("something")
}
}
// My code
protocol SayHelloProtocol {
func hello()
func name() -> String
}
extension SayHelloProtocol {
func hello() {
print("Hello " + name())
}
func name() -> String {
"someone"
}
}
class MyHelloObject: Object, SayHelloProtocol {
override func printSomething() {
hello()
}
}
class MyHelloChildObject: MyHelloObject {
func name() -> String {
"You"
}
}
MyHelloObject().printSomething()
MyHelloChildObject().printSomething()
This will print :
Hello someone
Hello someone
But I would like to override the method so it prints :
Hello someone
Hello You
Is it possible to override a method implemented in an extension ?
It works if you add the name() function also to MyHelloObject:
class MyHelloObject: Object, SayHelloProtocol {
override func printSomething() {
hello()
}
func name() -> String {
"Someone"
}
}
class MyHelloChildObject: MyHelloObject {
override func name() -> String {
"You"
}
}
The purpose of what I am trying to do is to make it possible to put objects which implements ChildOfRootClass to one array (look at AbstractClass -> children) and put at each ChildNClass instance object a link to its parent (look weak var delegate variable). So I want make type of delegate in each ChildOfRootClass generic.
Hope code will explain what exactly I have meant.
// Parent class for RootClass and Child1Class, Child2Class etc
class AbstractClass {
init() { }
init(smth: String) { }
var children = [String : ChildOfRootClass]()
func add(key: String, child: ChildOfRootClass) {
children[key] = child
}
}
Delegate protocols for each of children.
protocol ChildDelegate: class { }
protocol Child1ClassDelegate: ChildDelegate { func rr() }
protocol Child2ClassDelegate: ChildDelegate { }
class RootClass: AbstractClass {
override init() {
super.init()
}
}
extension RootClass: Child1ClassDelegate {
func rr() { }
}
Children classes.
protocol ChildOfRootClass {
associatedtype ChildOfRootClassDelegateType: ChildDelegate
weak var delegate: ChildOfRootClassDelegateType? { set get }
init(smth: String)
}
class Child1Class: AbstractClass, ChildOfRootClass {
typealias ChildOfRootClassDelegateType = Child1Delegate
weak var delegate: Child1Delegate?
required override init(smth: String) {
super.init(smth: smth)
}
}
extension Child1Class: Child2ClassDelegate { }
class Child2Class: AbstractClass/*, ChildOfRootClass*/ {
required override init(smth: String) {
super.init(smth: smth)
}
}
How I want to use it.
let root = RootClass()
let child1 = Child1Class(smth: "1")
let child2 = Child2Class(smth: "2")
child1.add(key: "child2", child: child2)
root.add(key: "child1", child: child1)
In the following code, my intention is to have repeatNum declared in the base class because it is used in the base class (inside init and other functions). And each subclass should set repeatNum because only the subclass knows its own value.
class Base {
var repeatNum: Int
init() {
for var i=0; i<repeatNum; ++i {
print("*")
}
}
}
class SubClass1 : Base {
override init() {
repeatNum = 10
super.init()
}
}
class SubClass2 : Base {
override init() {
repeatNum = 5
super.init()
}
}
Of course, it prompts some errors:
For the base class:
'self.repeatNum' not initialized
Return from initializer without initiating all stored properties.
For the subclasses:
use of 'self' in property access 'repeatNum' before super.init initializes self
I know I can simply call super.init() before setting repeatNum in the subclasses, but I really need to use repeatNum inside the base's init() in the real case. It becomes a paradox for me here somehow.
I also understand I can change the design to make the errors go away, but I am wondering if it's possible to achieve my original intention with some tweaks? I probably miss something here.
Your current code doesn't even compile, does it? It should complain about trying to use repeatNum before being initialized...
Maybe something like this could be an option for you?
class Base {
var repeatNum: Int
init(repeatNum: Int) {
self.repeatNum = repeatNum
for _ in 0..<repeatNum {
print("*")
}
}
}
class SubClass1 : Base {
init() {
super.init(repeatNum: 10)
}
}
class SubClass2 : Base {
init() {
super.init(repeatNum: 5)
}
}
i don't know what is you want,the following code is that ok
class Base {
var repeatNum: Int?
init() {
}
func printyourneed(){
for var i=0; i<repeatNum; ++i {
print("*")
}
}
}
class SubClass1 : Base {
override init() {
super.init()
self.repeatNum = 10
self.printyourneed()
}
}
class SubClass2 : Base {
override init() {
super.init()
self.repeatNum = 5
self.printyourneed()
}
}
or
class Base {
var _repeatNum:Int?;
var repeatNum: Int?{
get{
return _repeatNum
}
set{
_repeatNum = newValue
printyourneed()
}
}
init() {
}
func printyourneed(){
for var i=0; i<repeatNum; ++i {
print("*")
}
}
}
class SubClass1 : Base {
override init() {
super.init()
self.repeatNum = 10
}
}
class SubClass2 : Base {
override init() {
super.init()
self.repeatNum = 5
}
}