 
 // MARK: - AssociationOwner
 private extension AssociationOwner {
-    func _associate(_ object: AnyObject?, _ associationType: AssociationType, by key: inout Void?) {
+    func _associate<T: AnyObject>(_ object: T?, _ associationType: AssociationType, by key: inout AssociationKey) {
         switch associationType {
         case .strongly:
-            objc_setAssociatedObject(self, &key, object, .OBJC_ASSOCIATION_RETAIN);
+            self._stronglyAssociate(object, by: &key)
         case .weakly:
             self._weaklyAssociate(object, by: &key)
         }
     }
     
-    func _associatedObject<T: AnyObject>(for key: inout Void?) -> T? {
+    func _associatedObject<T: AnyObject>(for key: inout AssociationKey) -> T? {
         // First, we retrieve the associated object.
         let object: AnyObject? = objc_getAssociatedObject(self, &key) as AnyObject
         

// MARK: - AssociationOwner
// MARK: Protocol Declaration
public protocol AssociationOwner {
    func associate(_ object: AnyObject?, _ associationType: AssociationType, by key: inout AssociationKey)
    func associatedObject<T: AnyObject>(for key: inout AssociationKey) -> T?
}


// MARK: Default Implementations
public extension AssociationOwner {
    public func associate(_ object: AnyObject?, _ associationType: AssociationType, by key: inout AssociationKey) {
        self._associate(object, associationType, by: &key._key)
    }
    
    public func associatedObject<T: AnyObject>(for key: inout AssociationKey) -> T? {
        return self._associatedObject(for: &key._key)
    }
}


        // If there is a _WeakBox associated but it's empty,
        // we nil the association and return nil.
        guard let boxedObject: T = box.object as? T else {
            self._setAssociationToNil(for: &key)
            return nil
        }
        
