Nongeneric classes that inherit from generic classes not visible from objc


(Davide Mendolia) #1

Hi,

Maybe this has been asked before but I couldn't find it.

I would like to be able to give visibility of non-generic subclass of a
generic class to obj-c. Is there any limitation of the compiler knowing
that the type of the non-generic type is closed, to generate a compatible
version for obj-c?

Code Example:

class SwiftSuperType<T: NSObjectProtocol> : NSObject {

}

class NonGenericClass2: SwiftSuperType<NSObject> {

}

Or with a obj-c super class:

@interface ObjcSuperType<T: id<NSObject>> : NSObject

@end

class NonGenericClass: ObjcSuperType<NSObject> {

}

Actual Behaviour:

Non-generic classes are not visible in obj-c. If adding the @objc notation
we get the following error.

Actual error message:
Generic subclasses of '@objc' classes cannot have an explicit '@objc'
attribute because they are not directly visible from Objective-C

regards,

···

--
Davide Mendolia


(Charlie Monroe) #2

Hi Davide,

AFAIK this is not (easily) possible (please, correct me someone if I'm wrong) since Swift's generics aren't "lightweight" as ObjC generics are.

In ObjC, no matter what you use for the generics, you still have just 1 class that handles all call:

@interface MyClass<T> : NSObject
@end

@class A, B;

NSLog(@"%@", NSStringFromClass([MyClass<A *> self])); // MyClass
NSLog(@"%@", NSStringFromClass([MyClass<B *> self])); // MyClass

[MyClass<A *> self] == [MyClass<B *> self]; // YES

In Swift, when you compile the generic class, a class is generated for each type you use - example:

class MyClass<T> {}
class A {}
class B {}

NSStringFromClass(MyClass<A>.self) // _TtGC14__lldb_expr_417MyClassCS_1A_
NSStringFromClass(MyClass<B>.self) // _TtGC14__lldb_expr_417MyClassCS_1B_

MyClass<A>.self == MyClass<B>.self // false

This makes what you suggest very complicated.

···

On Dec 14, 2016, at 2:47 PM, Davide Mendolia via swift-evolution <swift-evolution@swift.org> wrote:

Hi,

Maybe this has been asked before but I couldn't find it.

I would like to be able to give visibility of non-generic subclass of a generic class to obj-c. Is there any limitation of the compiler knowing that the type of the non-generic type is closed, to generate a compatible version for obj-c?

Code Example:

class SwiftSuperType<T: NSObjectProtocol> : NSObject {

}

class NonGenericClass2: SwiftSuperType<NSObject> {

}

Or with a obj-c super class:

@interface ObjcSuperType<T: id<NSObject>> : NSObject

@end

class NonGenericClass: ObjcSuperType<NSObject> {

}

Actual Behaviour:

Non-generic classes are not visible in obj-c. If adding the @objc notation we get the following error.

Actual error message:

Generic subclasses of '@objc' classes cannot have an explicit '@objc' attribute because they are not directly visible from Objective-C

regards,

--
Davide Mendolia
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Tino) #3

For me, it wouldn't be important to access those classes from ObjC — but I would appreciate being able to use classes with generic ancestors in Xibs.


(Jordan Rose) #4

Right. Even though the class you want to expose isn't generic, its superclass is, and Objective-C needs to know the whole inheritance chain in order to use the class in any meaningful way.

Depending on what your use case is, you may be able to work with a @objc protocol instead (either imported or defined in Swift).

Jordan

···

On Dec 14, 2016, at 08:47, Charlie Monroe via swift-evolution <swift-evolution@swift.org> wrote:

Hi Davide,

AFAIK this is not (easily) possible (please, correct me someone if I'm wrong) since Swift's generics aren't "lightweight" as ObjC generics are.

In ObjC, no matter what you use for the generics, you still have just 1 class that handles all call:

@interface MyClass<T> : NSObject
@end

@class A, B;

NSLog(@"%@", NSStringFromClass([MyClass<A *> self])); // MyClass
NSLog(@"%@", NSStringFromClass([MyClass<B *> self])); // MyClass

[MyClass<A *> self] == [MyClass<B *> self]; // YES

In Swift, when you compile the generic class, a class is generated for each type you use - example:

class MyClass<T> {}
class A {}
class B {}

NSStringFromClass(MyClass<A>.self) // _TtGC14__lldb_expr_417MyClassCS_1A_
NSStringFromClass(MyClass<B>.self) // _TtGC14__lldb_expr_417MyClassCS_1B_

MyClass<A>.self == MyClass<B>.self // false

This makes what you suggest very complicated.

On Dec 14, 2016, at 2:47 PM, Davide Mendolia via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hi,

Maybe this has been asked before but I couldn't find it.

I would like to be able to give visibility of non-generic subclass of a generic class to obj-c. Is there any limitation of the compiler knowing that the type of the non-generic type is closed, to generate a compatible version for obj-c?

Code Example:

class SwiftSuperType<T: NSObjectProtocol> : NSObject {

}

class NonGenericClass2: SwiftSuperType<NSObject> {

}

Or with a obj-c super class:

@interface ObjcSuperType<T: id<NSObject>> : NSObject

@end

class NonGenericClass: ObjcSuperType<NSObject> {

}

Actual Behaviour:

Non-generic classes are not visible in obj-c. If adding the @objc notation we get the following error.

Actual error message:

Generic subclasses of '@objc' classes cannot have an explicit '@objc' attribute because they are not directly visible from Objective-C

regards,

--
Davide Mendolia
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Davide Mendolia) #5

Ok, I understand. But my use case is adding functionality to obj-c class
provided by the ios sdk through generics. As I see it's not something
possible, I will go for an implementation that's it's not checking the type
through generic at compile time.

···

On Wed, Dec 14, 2016 at 6:56 PM Jordan Rose <jordan_rose@apple.com> wrote:

Right. Even though the class you want to expose isn't generic, its
superclass is, and Objective-C needs to know the whole inheritance chain in
order to use the class in any meaningful way.

Depending on what your use case is, you may be able to work with a @objc
protocol instead (either imported or defined in Swift).

Jordan

On Dec 14, 2016, at 08:47, Charlie Monroe via swift-evolution < swift-evolution@swift.org> wrote:

Hi Davide,

AFAIK this is not (easily) possible (please, correct me someone if I'm
wrong) since Swift's generics aren't "lightweight" as ObjC generics are.

In ObjC, no matter what you use for the generics, you still have just 1
class that handles all call:

@interface MyClass<T> : NSObject
@end

@class A, B;

NSLog(@"%@", NSStringFromClass([MyClass<A *> self])); // MyClass
NSLog(@"%@", NSStringFromClass([MyClass<B *> self])); // MyClass

[MyClass<A *> self] == [MyClass<B *> self]; // YES

In Swift, when you compile the generic class, a class is generated for each
type you use - example:

class MyClass<T> {}
class A {}
class B {}

NSStringFromClass(MyClass<A>.self) // _TtGC14__lldb_expr_417MyClassCS_1*A*_
NSStringFromClass(MyClass<B>.self) // _TtGC14__lldb_expr_417MyClassCS_1*B*_

MyClass<A>.self == MyClass<B>.self // false

This makes what you suggest very complicated.

On Dec 14, 2016, at 2:47 PM, Davide Mendolia via swift-evolution < swift-evolution@swift.org> wrote:

Hi,

Maybe this has been asked before but I couldn't find it.

I would like to be able to give visibility of non-generic subclass of a
generic class to obj-c. Is there any limitation of the compiler knowing
that the type of the non-generic type is closed, to generate a compatible
version for obj-c?

Code Example:

class SwiftSuperType<T: NSObjectProtocol> : NSObject {

}

class NonGenericClass2: SwiftSuperType<NSObject> {

}

Or with a obj-c super class:

@interface ObjcSuperType<T: id<NSObject>> : NSObject

@end

class NonGenericClass: ObjcSuperType<NSObject> {

}

Actual Behaviour:

Non-generic classes are not visible in obj-c. If adding the @objc notation
we get the following error.

Actual error message:
Generic subclasses of '@objc' classes cannot have an explicit '@objc'
attribute because they are not directly visible from Objective-C

regards,

--
Davide Mendolia
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Derrick Ho) #6

Swift generics are swift only

Objective-c lightweight generics are not true generics but rather just
annotation that helps with interoperability.

Even though you are subclassing a generic class into a supposed non-generic
type it is still a generic. Inheritance follows an is-a relationship and
the subclass gets its generic genes from the parent class.

···

On Wed, Dec 14, 2016 at 1:06 PM Davide Mendolia via swift-evolution < swift-evolution@swift.org> wrote:

Ok, I understand. But my use case is adding functionality to obj-c class
provided by the ios sdk through generics. As I see it's not something
possible, I will go for an implementation that's it's not checking the type
through generic at compile time.

On Wed, Dec 14, 2016 at 6:56 PM Jordan Rose <jordan_rose@apple.com> wrote:

Right. Even though the class you want to expose isn't generic, its
superclass is, and Objective-C needs to know the whole inheritance chain in
order to use the class in any meaningful way.

Depending on what your use case is, you may be able to work with a @objc
protocol instead (either imported or defined in Swift).

Jordan

On Dec 14, 2016, at 08:47, Charlie Monroe via swift-evolution < > swift-evolution@swift.org> wrote:

Hi Davide,

AFAIK this is not (easily) possible (please, correct me someone if I'm
wrong) since Swift's generics aren't "lightweight" as ObjC generics are.

In ObjC, no matter what you use for the generics, you still have just 1
class that handles all call:

@interface MyClass<T> : NSObject
@end

@class A, B;

NSLog(@"%@", NSStringFromClass([MyClass<A *> self])); // MyClass
NSLog(@"%@", NSStringFromClass([MyClass<B *> self])); // MyClass

[MyClass<A *> self] == [MyClass<B *> self]; // YES

In Swift, when you compile the generic class, a class is generated for
each type you use - example:

class MyClass<T> {}
class A {}
class B {}

NSStringFromClass(MyClass<A>.self) // _TtGC14__lldb_expr_417MyClassCS_1*A*
_
NSStringFromClass(MyClass<B>.self) // _TtGC14__lldb_expr_417MyClassCS_1*B*
_

MyClass<A>.self == MyClass<B>.self // false

This makes what you suggest very complicated.

On Dec 14, 2016, at 2:47 PM, Davide Mendolia via swift-evolution < > swift-evolution@swift.org> wrote:

Hi,

Maybe this has been asked before but I couldn't find it.

I would like to be able to give visibility of non-generic subclass of a
generic class to obj-c. Is there any limitation of the compiler knowing
that the type of the non-generic type is closed, to generate a compatible
version for obj-c?

Code Example:

class SwiftSuperType<T: NSObjectProtocol> : NSObject {

}

class NonGenericClass2: SwiftSuperType<NSObject> {

}

Or with a obj-c super class:

@interface ObjcSuperType<T: id<NSObject>> : NSObject

@end

class NonGenericClass: ObjcSuperType<NSObject> {

}

Actual Behaviour:

Non-generic classes are not visible in obj-c. If adding the @objc notation
we get the following error.

Actual error message:
Generic subclasses of '@objc' classes cannot have an explicit '@objc'
attribute because they are not directly visible from Objective-C

regards,

--
Davide Mendolia
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution