Class Does Not Implement Its Superclass'S Required Members

Class does not implement its superclass's required members

From an Apple employee on the Developer Forums:

"A way to declare to the compiler and the built program that you really
don't want to be NSCoding-compatible is to do something like this:"

required init(coder: NSCoder) {
fatalError("NSCoding not supported")
}

If you know you don't want to be NSCoding compliant, this is an option. I've taken this approach with a lot of my SpriteKit code, as I know I won't be loading it from a storyboard.


Another option you can take which works rather well is to implement the method as a convenience init, like so:

convenience required init(coder: NSCoder) {
self.init(stringParam: "", intParam: 5)
}

Note the call to an initializer in self. This allows you to only have to use dummy values for the parameters, as opposed to all non-optional properties, while avoiding throwing a fatal error.


The third option of course is to implement the method while calling super, and initialize all of your non-optional properties. You should take this approach if the object is a view being loaded from a storyboard:

required init(coder aDecoder: NSCoder!) {
foo = "some string"
bar = 9001

super.init(coder: aDecoder)
}

Swift: Implementing Protocol Initializer in a Class

Surely the designated superclass initializer would be inherited?

No, not always. If the subclass defines its own designated initialisers, then it won't automatically inherit the superclass' designated initialisers. Consider the following example:

class Foo {
init() {}
}

class Bar : Foo {

var str: String

init(str: String) {
self.str = str
}
}

let b = Bar() // illegal – what value would the 'str' property have?

As Bar defines its own init(str:) designated initialiser, it doesn't automatically inherit Foo's designated initialiser init(). This prevents unsafe initialisation in cases where the subclass declares its own stored properties.

Marking init() as required enforces Bar has an init(), be it through providing its own implementation:

class Foo {
required init() {}
}

class Bar : Foo {

var str: String

init(str: String) {
self.str = str
}

// implement required init(), as Bar defines its own designated initialiser.
required init() {
self.str = "foo" // now str is correctly initialised when calling init()
}
}

let b = Bar() // now legal

Or by inheriting Foo's implementation (when Bar doesn't define its own designated initialisers):

class Foo {
required init() {}
}

class Bar : Foo {
// inherits init() from Foo, as Bar doesn't define its own designed initialisers.
}

let b = Bar() // legal

Designated Initializer?

Example:

There is a superclass A with an initWithName: DI.

Now you create subclass B. If you want the same DI and you don't need any additional initialization, then there is nothing to do with the init method. You simply call:

B *someBObject = [[B alloc] initWithName:@"A Name"];

This creates the B object and calls the initWithName: method from A.

Now if your B class needs to do supplemental work in the initWithName: method, then you add this to B.m:

- (instancetype)initWithName:(NSString *)name {
self = [super initWithName:name];
if (self) {
// do some additional stuff to initialize this "B" instance
}

return self;
}

Using subclass' method in superclass

Given the types above, anExpressionOfTypeSubClassOrIClass.implementedMethod() must be used. Note that the Type of an expression - the view it provides - must have the method intended to be used. In this case, an expression of type SuperClass cannot be used here because it has no declared implementedMethod member.

One approach - and arguably the preferred approach - is to use abstract methods. Even though abstract methods are not strictly required for Polymorphism they describe scenarios such as this where a subclass should provide the implementation. (The abstract methods could be replaced with empty method expecting - but not requiring - to be overridden in sublcasses, but why not use abstract for its designed purpose?)

abstract class SuperClass implements IClass {
// Don't implement this, but declare it abstract
// so that we can conform to IClass as well
public abstract void implementedMethod();

public void method () {
// Now this object (which conforms to IClass) has implementedMethod
// which will be implemented by a concrete subclass.
implementedMethod();
}
}

This has the "negative" aspects that SuperClass cannot be directly instantiated (it is abstract, after all) and that SuperClass must implement (or, as shown, delegate out via abstract) the expected signature. In this case I also chose to make SuperClass implement IClass even though it's not strictly required because it guarantees that the SuperClass and all subclasses can be viewed as an IClass.

Alternatively, remember that Types of Expressions are just views of objects and are not necessarily the same as the actual Concrete Type of object. While I would advise against using the following code because it loses some type-safety, I think it shows the important point.

class SuperClass {
public void method () {
// We try to cast and NARROW the type to a
// specific "view". This can fail which is one
// reason why it's not usually appropriate.
((IClass)this).implementedMethod();
}
}

class SubClass extends SuperClass implements IClass {
// ..
}

class BrokenSubClass extends SuperClass () {
}

// OK! Although it is the SAME OBJECT, the SuperClass
// method can "view" the current instance (this) as an IClass
// because SubClass implements IClass. This view must be
// explicitly request through a cast because SuperClass itself
// does not implement IClass or have a suitable method to override.
(new SubClass()).method();

// BAD! ClassCastException, BrokenSubClass cannot be "viewed" as IClass!
// But we didn't know until runtime due to lost type-safety.
(new BrokenSubClass()).method();

How to access a protected method of superclass in a subclass?

Your main() method cannot access the superclass implementation of demoMethod() -- because it's overridden in the child class.

Your main() method can access demoMethod(), through a reference of the subclass type, even though it's protected, because it's in the same package as your subclass. But it will call the subclass implementation.

But if you're "using superclass object reference to call demoMethod", the method will not be accessible, and your code will not compile. Your superclass is in a different package. Methods marked protected can only be accessed by subclasses and by code in the same package.

If you made the method public in both subclass and superclass, calling demoMethod() would call the subclass implementation, regardless whether the reference was of the super or subclass type.

An instance of the subclass can call super.demoMethod() as part of the implementation of its methods. But the main() method cannot.

Using properties of SKSpriteNode for subclass

Not sure if this is what you're asking, but, generally, if you create a subclass of an object, you don't need to do anything special to access the superclass's properties. They'll be initialized in the usual fashion.

However, you DO have to ensure that the superclass's initializers get called in a proper manner if you have your own initializers for your subclass.

In the case of a subclass of SKSpriteNode, if you define your own initializer for the subclass, that initializer will need to call the designated superclass initializer, which passes in the texture, color, and size to use for the sprite:

init(enemyType:String) {
let texture = SKTexture(imageNamed: "enemy_\(enemyType)")
let color = UIColor.black
let size = texture.size()
super.init(texture: texture, color: color, size: size)
}

Is there a specific way to give a certain subclass some functions of the superclass?

All methods defined in a superclass are available at deriving classes but with Java 8 you might be able to get something like this by using default-methods in interfaces. So instead of one abstract class containing all possible methods you might implement four interfaces

public interface Searchable {
public String getIndexPath();
}

public interface PhraseSearchable extends Searchable {
public default void phraseSearch() {
String indexPath = getIndexPath();
// do the search
}
}

public interface TermSearchable extends Searchable {
public default void termSearch() {
String indexPath = getIndexPath();
// do the search
}
}

public interface CategorySearchable extends Searchable {
public default void categorySearch() {
String indexPath = getIndexPath();
// do the search
}
}

To avoid duplicate code you can create an abstract class

public abstract class AbstractSearchable implements Searchable {
private String indexPath;

public AbstractSearchable(String indexPath) {
this.indexPath = indexPath;
}

// other methods that might be useful
}

Your actual classes can then implement the corresponding interfaces

public class ReviewIndex extends AbstractSearchable implements CategorySearchable {
public ReviewIndex() {
super("./review_index/");
}
}
public class TipIndex extends AbstractSearchable implements PhraseSearchable, TermSearchable {
public ReviewIndex() {
super("./review_index/");
}
}

If this is possible depends heavily on the actual implementation of the search methods. Interfaces can't contain any members, etc. so these methods must be able to run for themselves (like a static method without using any static members of the class). You might to overcome this problem by adding more methods to the Searchable interface that provide the data and do the implementation in the abstract class but that might expose internal stuff to the public because all the declared methods in an interface are public.

Swift - how do I pass a type/object (name or instance) into a method and then (a) get the type (b) instantiate it?

You can use the .dynamicType property of an instance to get its type. Then you can call a required init method on it (or any other class/static method).

let theType = object.dynamicType
let newInstance = theType.init()

Note: This code compiles, depending on the type of object. If the type has a required init() method, it is safe to call on the dynamicType. However, it also appears that if the type is NSObject the compiler will let you call init() on the dynamicType even though a subclass may or may not have an init() method given how Swift initializer inheritance works. Arguably this is a bug in the compiler, so use this code with caution if you choose to do so. Thanks to @nhgrif for the discussion on the topic.



Related Topics



Leave a reply



Submit