Implement ExpressibleByStringLiteral on abstract base class - swift

I have a pretty simple class structure where an "abstract" base class, Node, is implemented in a few concrete subclasses. In my case the base class represents the common interface to the object and therefore most type references are purely Node for simplicity.
However what I want to do now is implement support for ExpressibleByStringLiteral on the abstract Node such that I can instantiate a specific (of my choosing) concrete subclass when a String is interpreted as a Node.
The problem is ExpressibleByStringLiteral doesn't seem to want to allow me to do this because it requires I implement a required initializer as opposed to a static function (which would make way more sense, imo). I've gotten it able to work on one of the concrete subclasses, but that's pretty useless to me given that the concrete type is rarely used explicitly (and in fact I'd prefer it not be), as everything goes through the base Node type.
What I want is to be able to do this:
let node: Node = "textual representation of a node"
Since the subclasses are still Nodes, this doesn't violate any object oriented principles, yet Swift doesn't seem to want to let me do it.
Is there any way around this, or is this just a limitation of ExpressibleByStringLiteral?

Related

Relation between Existential Container and struct instance which conform protocol

I'm trying to understand how to find protocol method's implementation.
I know that Swift uses an Existential Container for fixed-size storage in Stack memory which manages how to describe an instance of a struct in memory. and it has a Value Witness Table (VWT) and Protocol Witness Table (PWT)
VWTs know how to manage real value in instance of struct (their lifecycle) and PWTs know the implementation of protocol's method.
But I want know the relation between the instance of a struct and the "existential container".
Does an instance of struct have a pointer which refers to an existential container?
How does an instance of a struct know its existential container?
Preface: I don't know how much background knowledge you have, so I might over-explain to make sure my answer is clear.
Also, I'm doing this to the best of my ability, off by memory. I might mix up some details, but hopefully this answer could at least point you towards further reading.
See also:
https://stackoverflow.com/a/41490551/3141234
https://github.com/apple/swift/blob/main/docs/SIL.rst#id201
In Swift, protocols can be used "as a type", or as a generic constraint. The latter case looks like so:
protocol SomeProtocol {}
struct SomeConformerSmall: SomeProtocol {
// No ivars
}
struct SomeConformerBig: SomeProtocol {
let a, b, c, d, e, f, g: Int // Lots of ivars
}
func fooUsingGenerics<T: SomeProtocol>(_: T) {}
let smallObject = SomeConformerSmall()
let bigObject = SomeConformerBig()
fooUsingGenerics(smallObject)
fooUsingGenerics(bigObject)
The protocol is used as a constraint for type-checking at compile time, but nothing particularly special happens at runtime (for the most part). Most of the time, the compiler will produced monomorphized variants of the foo function, as if you had defined fooUsingGenerics(_: SomeConformerSmall) or fooUsingGenerics(_: SomeConformerBig) to begin with.
When a protocol is "used like a type", it would look like this:
func fooUsingProtcolExistential(_: SomeProtocol) {}
fooUsingGenerics(smallObject)
fooUsingGenerics(bigObject)
As you see, this function can be called using both smallObject and bigObject. The problem is that these two objects have different sizes. This is a problem: how will the compiler know how much stack space is necessary to allocate for the arguments of this function, if the arguments can be different sizes? It must do something to help fooUsingProtcolExistential accommodate that.
Existential containers are the solution. When you pass a value where a protocol type is expected, the Swift compiler will generate code that automagically boxes that value into an "existential container" for you. As currently defined, an existential container is 4 words in size:
The first word is a pointer to the Protocol Witness Table (more on this later)
The next three words are inline storage for the value.
When the value being stored is less than 3 words in size (e.g. SomeConformerSmall), the value is packed directly inline into that 3 word buffer. If the value is more than 3 words in size (e.g. SomeConformerSmall), a ARC-managed box is allocated on the heap, and the value is copied into there. A pointer to this box is then copied into the first word of the existential container (the last 2 words are unused, IIRC).
This introduces a new issue: suppose that fooUsingProtcolExistential wanted to forward along its parameter to another function. How should it pass the EC? fooUsingProtcolExistential doesn't know whether the EC contains a value-inline (in which case, passing the EC just entails copying its 4 words of memory), or heap-allocated (in which case, passing the EC also requires an ARC retain on that heap-allocated buffer).
To remedy this, the Protocol Witness Table contains a pointer to a Value Witness Table (VWT). Each VWT defines the a standard set of function pointers, that define how the EC can be allocated, copied, deleted, etc. Whenever a protocol existential needs to be manipulated in someway, the VWT defines exactly how to do so.
So now we have a constant-size container (which solves our heterogeneously-sized parameter passing problem), and a way to move the container around. What can we actually do with it?
Well at a minimum, values of this protocol type must at least define the required members (initializers, properties (stored or computed), functions and subscripts) that the protocol defines.
But each conforming type might implement these members in a different way. E.g. some struct might satisfy a method requirement by defining the method directly, but another class might satisfy it by inheriting the method from a superclass. Some might implement a property as a stored property, others as a computed property, etc.
Handling these incompatibilities is the primary purpose of the Protocol Witness Table. There's one of these tables per protocol conformance (e.g. one for SomeConformerSmall and one for SomeConformerBig). They contain a set of function pointers with point to the implementations of the protocols' requirements. While the pointed-to functions might be in different places, the PWT's layout is consistent for the protocol is conforms to. As a result, fooUsingProtcolExistential is able to look at the PWT of an EC, and use it to find the implementation of a protocol method, and call it.
So in short:
An EC contains a PWT and a value (inline or indirect)
A PWT points to a VWT
My understanding:
Struct doesn't know where existential container/value witness table/protocol witness table is, the compiler knows. If needed somewhere, compiler pass them to there.

Is it better to implement two classes or one class in the following case?

I have a class "Vertex" with 4 attributes and a class "Vertex_" with one attribute. The one attribute in Vertex_ is also in Vertex. Is it a good design to keep the two classes or is it better to program just the class Vertex, although there will be 3 variables, which are not used, when I instantiate an object which needs just the one attribute?
Class Vertex_ is actually somewhat a duplicate of Class Vertex.
I would suggest using inheritance and having Class Vertex inherit the attribute from the parent Class Vertex_ while having the 3 other attributes Class Vertex_ does not have.
TL;DR
This is a question that deserves a very long answer.There are two reasons for inheritance and the reason for doing it can depend on the language being used. One reason is for code reuse. Without knowing anything else about your situation, it would seem you are inheriting simply to reuse an attribute (but I suspect there could be more you will be reusing). But, there are other ways of getting code reuse without inheritance, for example containment, which is often a better way.
A powerful feature of object-oriented programming is the ability to substitute one type of object for another. When a message is sent to that object, the correct method implementation is invoked according the actual type of object receiving the message. This is one type of polymorphism. But in some languages the ability to substitute one object for another is constrained. In Java I can only substitute an instance of class B for an instance of class A if B is a descendant of A. So inheritance becomes important in Java to support polymorphism.
But what does it mean to be able to substitute a B instance for an A instance? Will it work? Class A has established a contract stating what each of its methods requires before you can successfully call it and at the same time states what each method promises to deliver. Will the methods of class B live up to that contract? If not, you really cannot substitute a B for an A and expect the program to run correctly. B may be a subclass of A but it is not a subtype of A (see Liskov substitution principle]).
In a language such as Python, inheritance is not required for polymorphism and coders are more apt to use it as code-reuse mechanism. Nevertheless, some people feel that subclassing should only be used to express subtyping. So, if Vertex_ is only using one of the four attributes it has inherited, I am doubtful that an instance of Vertex_ could be safely substituted for an instance of Vertex. I would not do the inheritance unless the language were C++ and then I would use private inheritance.

A guess that the Swift type alias mechanism is the automatic initializer Inheritance

The question popped in my head, what is happening when I define a Swift type alias? What is the mechanism behind it? Until I learned the Automatic Initializer Inheritance chapter from the Swift official document:
If your subclass doesn't define any designated initializer, it automatically inherits all of its superclass designated initializers
And here is my practice code for learning
class Vehicle{
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheel(s)"
}
}
class Auto: Vehicle{}
let VM = Auto()
VM.numberOfWheels
Wow! this works,at least performs, exactly as the Swift type alias. Auto is the alias of the type Vehicle
Question: Am I understand it right? This is the mechanism behind type alias.
Question: Am I understand it right? This is the mechanism behind type alias.
NO, typealises and subclassing (with inheriting all methods and initializers) are different things and based on different semantics and mechanisms.
let v1 = Vehicle()
v1 is Auto //->false
typealias Norimono = Vehicle
v1 is Norimono //->true (with warning "'is' test is always true)
The last result (including the warning you may find) is exactly the same as v1 is Vehicle.
Typealias is literally an alias, it's giving another name for the same type.
One more, you can define typealias of structs or enums, which you cannot define inherited classes (types).
Not really, but if you've never seen object oriented programming they could look somewhat similar, i agree.
Auto is a subclass that extends the original vehicle and could add additional properties and method to the Vehicle even if in that example it doesn't do it.
Auto and Vehicle are not the same thing, a Vehicle is a basic type and and Auto is one of its subtypes, what you can do with a Vehicle you can do with an Auto but not vice-versa.
A typealias is just an alias, a way to give and additional "name" to a pre-existing type, just that. A type and his alias are the same thing.

In Scala, plural object name for a container of public static methods?

I've written a Scala trait, named Cache[A,B], to provide a caching API. The Cache has the following methods, asyncGet(), asyncPut(), asyncPutIfAbsent(), asyncRemove().
I'm going to have a few static methods, such as getOrElseUpdate(key: A)(op: => B). I don't want methods like this as abstract defs in the Cache trait because I don't want each Cache implementation to have to provide an implementation for it, when it can be written once using the async*() methods.
In looking at Google Guava and parts of the Java library, they place public static functions in a class that is the plural of the interface name, so "Caches" would be the name I would use.
I like this naming scheme actually, even though I could use a Cache companion object. In looking at much of my code, many of my companion objects contain private val's or def's, so users of my API then need to look through the companion object to see what they can use from there, or anything for that matter.
By having a object named "Caches" is consistent with Java and also makes it clear that there's only public functions in there. I'm leaning towards using "object Caches" instead of "object Cache".
So what do people think?
Scala's traits are not just a different name for Java's interfaces. They may have concrete (implemented) members, both values (val and var) and methods. So if there's a unified / generalized / shared implementation of a method, it can be placed in a trait and need not be replicated or factored into a separate class.
I think the mistake starts with "going to have a few static methods". Why have static methods? If you explain why you need static methods, it will help figure out what the design should be.

Pseudo-multiple-inheritance with extension methods on interfaces in C#?

Similar question but not quite the same thing
I was thinking that with extension methods in the same namespace as the interface you could get a similar effect to multiple inheritance in that you don't need to have duplicate code implementing the same interface the same way in 10 different classes.
What are some of the downsides of doing this? I think the pros are pretty obvious, it's the cons that usually come back to bite you later on.
One of the cons I see is that the extension methods can't be virtual, so you need to be sure that you actually do want them implemented the same way for every instance.
The problem that I see with building interface capability via extension methods is that you are no longer actually implementing the interface and so can't use the object as the interface type.
Say I have a method that takes an object of type IBar. If I implement the IBar interface on class Foo via extension methods, then Foo doesn't derive from IBar and can't be used interchangeably with it (Liskov Substitution principle). Sure, I get the behavior that I want added to Foo, but I lose the most important aspect of creating interfaces in the first place -- being able to define an abstract contract that can be implemented in a variety of ways by various classes so that dependent classes need not know about concrete implementations.
If I needed multiple inheritance (and so far I've lived without it) badly enough, I think I'd use composition instead to minimize the amount of code duplication.
A decent way to think about this is that instance methods are something done by the object, while extension methods are something done to the object. I am fairly certain the Framework Design Guidelines say you should implement an instance method whenever possible.
An interface declares "I care about using this functionality, but not how it is accomplished." That leaves implementers the freedom to choose the how. It decouples the intent, a public API, from the mechanism, a class with concrete code.
As this is the main benefit of interfaces, implementing them entirely as extension methods seems to defeat their purpose. Even IEnumerable<T> has an instance method.
Edit: Also, objects are meant to act on the data they contain. Extension methods can only see an object's public API (as they are just static methods); you would have to expose all of an object's state to make it work (an OO no-no).