How to Refer to a Global Type from Within a Class That Has a Nested Type with The Same Name

How to refer to a global type from within a class that has a nested type with the same name?

Use typealias

class Address {
var someProperty: String?
}

typealias GlobalAddress = Address

class ThirdPartyAPI {
class Address {
var someOtherProperty: String?
init(fromAddress address: GlobalAddress) {
self.someOtherProperty = address.someProperty
}
}
}

Accessing outer class with same name as nested class

If you don't want to wrap it in namespaces you can use global:: to refer to types inside the global namespace:

public class Outer
{
private global::Inner inner = new global::Inner();
private class Inner
{
}
}

public class Inner
{
}

How do I create an instance of a nested class from within that class in Python?

Your error comes from how python handles classes.

When it encounters a class statement, the body of the class is run, and the names it defines are placed in a separate namespace, which will eventually become the class __dict__. The class object is not created and bound to its name until (well) after the body has run. That means that when you put class NestedClass: inside the body of class ExampleClass:, ExampleClass does not exist yet, and neither does NestedClass. Indirectly because of this, all the new class namespaces live in the top level available namespace (e.g. global or function), and are not actually nested within one another.

As a consequence of this order of operations, class bodies are not aware of the namespaces of surrounding classes at all. So the namespace of NestedClass looks out to the global namespace, not to the __dict__ of ExampleClass, as you might expect coming from say Java. A class defined in a function would be able to see the functions local namespace before globals, but still not that of an enclosing class.

And so, the line newclass = NestedClass() raises an error. The name NestedClass does not exist in the function's namespace, or in the global namespace. There are three simple workarounds available:

  1. Use the staticly scoped __class__:

    newclass = __class__()
  2. Refer to the class by its global name:

    newclass = ExampleClass.NestedClass()
  3. Don't use nested classes in Python. This is generally the preferred approach. Just move NestedClass to the top level. Then your makenew method will work without modification, and ExampleClass.Example can refer to NestedClass directly instead of as self.NestedClass.

A class name introduced inside a class is not treated as a nested class name

g++'s behavior here is entirely correct. This is specified in §3.3.2 [basic.scope.pdecl]/p7 of the standard:

The point of declaration of a class first declared in an
elaborated-type-specifier is as follows:

  • for a declaration of the form

    class-key attribute-specifier-seqopt identifier ;
    the identifier is declared to be a class-name in the scope that contains
    the declaration, otherwise
  • for an elaborated-type-specifier of the form

    class-key identifier
    if the elaborated-type-specifier is used in the decl-specifier-seq or parameter-declaration-clause of a
    function defined in namespace scope, the identifier is declared as a
    class-name in the namespace that contains the declaration; otherwise, except as a friend declaration*, the identifier is declared
    in the smallest namespace or block scope that contains the
    declaration.

Note that in the second case the declaration is always placed in a namespace or block scope, never a class scope, so it can never declare a nested class. Also, in the second case, a lookup will be performed and only if a previously declared type-name is not found will the elaborated-type-specifier be taken to declare a new name (§3.4.4 [basic.lookup.elab]/p2, §9.1 [class.name]/p3 note).


* Friend declarations have their own weird rules. The names first declared in friend declarations are still placed in namespace (for non-local classes) or block (for local classes) scope, but they are not made visible for most name lookup (except for ADL in case of functions) until they are also declared in the scope containing them. The rules for non-local classes are specified in §7.3.1.2 [namespace.memdef]/p3:

If a friend declaration in a non-local class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by unqualified lookup (3.4.1) or by qualified lookup (3.4.3) until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship). If a friend function is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments (3.4.2). If the
name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.

The rules for local classes are specified in §11.3 [class.friend]/p11:

If a friend declaration appears in a local class (9.8) and the name specified is an unqualified name, a prior declaration is looked up without considering scopes that are outside the innermost enclosing non-class scope. [...] For a friend class declaration, if there is no prior declaration, the class that is specified belongs to the innermost enclosing non-class scope, but if it is subsequently referenced, its name is not found by name lookup until a matching declaration is provided in the innermost enclosing non-class scope.

C++ multiple nested template types inside outer template class referring to each other

Two things wrong with that code:

1 You can't use Node before it is declared. So move that private block up top.

2 NodeList<E>::Node<E> must be NodeList<T>::Node<E>, or simply Node<E> as you are already in the Nodelist<T> class.

template <typename T>
class NodeList
{
typedef T value_type;
template <typename E = value_type> struct Node
{
E element;
Node<E> *prev;
Node<E> *next;

};
public:
template <typename E>
class Iterator
{
template <typename> friend class NodeList;
public:
E& operator*();
bool operator==(const Iterator&) const;
bool operator!=(const Iterator&) const;
Iterator& operator++();
Iterator operator++(int);
Iterator& operator--();
Iterator operator--(int);
private:
Node<E> *node;
Iterator(Node<E> *node);
};


};

template <typename T>
template <typename E>
NodeList<T>::Iterator<E>::Iterator(NodeList<T>::Node<E> *node)
{

}

I can think of cases where a Nodelist<E>::Node<E> could be a desired in the subclass or even the class itself but that either needs a different syntax or maybe isn't even supported. But I think in this case Nodelist<T>::Node<E> is actually the desired type.

Why can't inner class and outer class have same name?

Class X already has a member named X, referring to itself. This is known as an injected class name. It's then invalid to add another member with the same name.

In swift, how to refer to topmost class when my class has subclass of same name

One usual way is to bind your outer class into struct. This pattern is quite similar to creating a namespace. You could do it like this

struct MyNameSpace {
class myObject {
init(message: String) {
print(message)
}
}
}
//here I define a global works fine
let global = MyNameSpace.myObject(message: "this works")

//other class
class ViewController: UIViewController {
//defines a subclass with same name
class myObject {
func failsFunction(){
//cannot invoke initializer for type "ViewController.myObject" with an argument of type (String)
let innerObj = MyNameSpace.myObject(message: "how can I refer to the topmost myObject here?")
}
}

}

Then, you could use both the classes and the compiler determines the use cases differently for both.



Related Topics



Leave a reply



Submit