I'm building a set of objects to represent the data abstraction layer sitting between my angularjs application and the backend API. I'm using coffeescript for this (partly to learn coffeescript, partly because I am enjoying their class implementation as I originally hail from a c++ and java background from Days of Yore).
So I have something like
Class Animal
#_cache: {}
...stuff...
Class Dog extends Animal
#_cache: {}
and so on. The issue (which is clearly a syntactic sugar thing) is that I'd like to have all concrete subclasses of Dog have their own instance of the cache. I can handle it either by how I did it above (just override the property), or by replacing that cache with something like #_cache[#constructor.name] = {}, and writing cache accessor functions instead of just directly interacting with it.
Basically, the pattern I want to express is: "Property #{name} should be a class-level (or static) property on this object, and all extending classes should have their own instance of this property", without manually having to do that on each child type. Is there a reasonable pattern to do this?
I have a suggestion, using the dynamic pointer of an instance to its own class: #constructor
In this example, the cache is initialized at first instance creation, and populated in the constructor itself.
class Animal
# is is just here to distinguish instances
id: null
constructor:(#id) ->
# #constructor aims at the current class: Animal or the relevant subclass
# init the cache if it does not exists yet
#constructor._cache = {} unless #constructor._cache?
# now populates the cache with the created instance.
#constructor._cache[#id] = #
class Dog extends Animal
# no need to override anything. But if you wish to, don't forget to call super().
# creates some instances
bart = new Animal 1
lucy = new Dog 1
rob = new Dog 2
console.log "animals:", Animal._cache
# prints: Object {1=Animal}
console.log "dogs:", Dog._cache
# prints: Object {1=Dog, 2=Dog}
see this fiddle (results on console)
Related
I have read how companion and singleton objects can be used to keep static methods, which makes sense. My question is how is this object made or instantiated it? I have read from some sources on how Objects are instances of the class if used as companion objects while others say they are not instances of the class. Then how are the objects existing or being made? Plus the Object would be same class data type I suppose?
My question is how is this object made or instantiated it?
[…]
Then how are the objects existing or being made?
You don't know, shouldn't know, and can't know.
The Scala Language Specification says that they exist. The Scala Language Specification does not say how they are instantiated. Every implementor is free to implement them however they want.
For example, ECMAScript has object literals, so for Scala.js, there is no need for them to be an instance of any class at all. Scala-native is not dependent on any platform, so it can do whatever it wants. Scala-JVM needs to comply with the restrictions of the JVM, where every object needs to be an instance of a class. In Scala-JVM, every singleton object Foo is an instance of a JVM class named Foo$.
Plus the Object would be same class data type I suppose?
The type of a singleton object Foo is the singleton type Foo.type. It's not a class.
I have read from some sources on how Objects are instances of the class if used as companion objects while others say they are not instances of the class.
Instead of reading "some sources", it's much better to just read the source: the Scala Language Specification, specifically section 5.3.2 Case Classes:
A case class definition of 𝑐[tps](ps1)…(ps𝑛) with type parameters tps and value parameters ps implies the definition of a companion object, which serves as an extractor object. It has the following shape:
object 𝑐 {
def apply[tps](ps1)…(ps𝑛): 𝑐[tps] = new 𝑐[Ts](xs1)…(xs𝑛)
def unapply[tps](𝑥: 𝑐[tps]) =
if (x eq null) scala.None
else scala.Some(𝑥.xs11,…,𝑥.xs1𝑘)
}
Each object has its own class, but you can't access the class directly. This class has a constructor without parameters which is called automatically when it's loaded and creates the only instance.
Objects are instances of the class if used as companion objects
Either you misunderstood or you really shouldn't trust these sources. It's possible for a companion object to extend the trait/class it's companion to, but not at all common.
Companion objects are not instances of the class they're companion of, think of them more like a collection of utility methods. If you're familiar with Java - all the method, that you made static in Java (hence they don't belong to a particular instance, but to class in general) would go to Companion object in Scala. Also, companion objects have access to classes private values.
Objects are lazily initialized for you, you don't need to know when and how exactly are they created, just if you call a function from an object - it will be created for you, and there will be only one instance of it.
What is the reason that
trait Dog {
def bark = "woof"
}
object Dog extends Dog
works, but the following does not
trait Dog {
def bark = "woof"
}
class Dog extends Dog
I read somewhere that in the first case mentioned above the object is not a companion object. What is the scenario when object and trait should have the same name ?
From introduction to Chapter 2 (Identifiers, Names & Scopes):
There are two different name spaces, one for types and one for terms.
Section 5.5 (Object definitions) contains almost exactly your example (with Point instead of Dog), with the following comment:
Note that the double use of the name Point is legal, since the class definition defines the name Point in the type name space, whereas the object definition defines a name in the term namespace.
(emphasis mine)
Your second example with class Dog extends Dog does not work, because both the class Dog and trait Dog end up in the namespace for types, and this results in a conflict.
Companion objects are used whenever you would use static methods in e.g. Java (except that companion objects are much nicer, because they are, well, objects, and can be passed around as ordinary values).
The situation object Foo extends Foo appears somewhat contrived and rather uncommon. Have you an actual example where it is used? If not, then it's just a corner case that is formally valid, simply because it's not explicitly prohibited.
EDIT: object AnsiColor extends AnsiColor seems to be one of the most "important" applications of the object X extends X pattern.
The reason the second example fails here, is not because Dog is not a companion object, but because you define a new duplicate class Dog. I always view traits and classes as one category, and objects as another - and object is an singleton instance of either trait or class.
Why you can't create classes with the same name?
It's impossible to distinguish two entities if that's allowed.
Why you can create (class/trait) and object with the same name?
You can distinguish them, because class or trait is type and object is a value.
When should you name your objects the same name as classes?
If you wan't to define companion object, so your implicits for the object would work. Or if you want to define convenient apply method on an object. Otherwise I don't bother myself at all with either object is companion or not, but often create objects with the class name for convenience.
I'm new to Scala with Java background.
In java when we want to share any field among different objects of class. we declare that field static.
class Car {
static NO_Of_TYRES = 4;
// some implementation.
public int getCarNoOftyres(){
NO_Of_TYRES; // although it's not a good practice to use static without class name
//but we can directly access static member in same class .
}
}
But in Scala we cannot declare static fields in class, we need to use object(companion object) for that.
In scala we will do like this,
class Car {
println(NO_Of_TYRES); // scala doesn't let us do that. gives error
println(Car.NO_Of_TYRES);// this is correct way.
}
object Car {
val NO_Of_TYRES: Int = 4;
}
I'm just curious, how scala treat companion objects?
what different these two key-words (class and object) makes ?
why does scala not letting us access NO_Of_TYRES directly in class?
Companion objects are singleton class instances (and definitions), just to recall singleton in java is more or less:
class Foo {
private Foo() { }
/* boilerplate to prevent cloning */
private static Foo instance = new Foo();
public static Foo getInstance() { return instance; }
public int bar() { return 5; }
}
and then to call method bar of this object:
Foo.getInstance().bar();
Scala removed all this boilerplate and lets you create equivalent thing with just
object Foo {
def bar: Int = 5
}
and to call it you only need
Foo.bar
now what's the difference between 'object' and 'companion object'? It's actually quite simple - companion object (so the object defined in the same file as a class and having the same name) has access to it's related class private fields and methods, and that's probably why scala authors decided that it should reside in the same file - so that references to private fields are in the same file as their declarations (which I think is always the case both in Java and Scala, unless using reflection magic)
I'd like to reference another answer about the same subject: What are the advantages of Scala's companion objects vs static methods?
See also Section 4.3 of Odersky's book Programming in Scala - Chapter 4 - Classes and Objects
Scala treats everything as pure objects with their instances. In this view a java static member is not part of any instance, it lives a separate and different life.
With the tricks of the keyword object and some syntactic sugar, you can achieve the same result but maintaining the stated principle: a single instance of that object is instantiated and a global access point for the instance is provided.
Scala, as you pointed out, cannot have static variables or methods, as known in Java. Instead, there are singleton objects, which are declared with the keyword object. Calling a method in this objects is like calling a static method in Java, except you are calling the method on a singleton object instead.
If this object has the same name of a class or trait, it is called the companion object of the class/trait. A companion object must be defined inside the same source file as the class/trait. A companion object differs from other objects as it has access rights to the related class/trait that other objects do not. In particular it can access methods and fields that are private in the class/trait.
Companion objects provide us with a means to associate functionality with a class without associating it with any instance of that class. They are commonly used to provide additional constructors
Ok. I am trying to extend a data structure class by making a subclass. The use case is that the program will already have an instance of the parent class and pass that to the constructor of the subclass. In other words, I have an instance of a parent class, A, and I want to feed it into an extended class constructor to get an instance of the extended class, B.
class child(Parent):
def __init__ (self, dataInstance=None):
super(child, self).__init__(dataInstance)
child.someparentmethod() # YES!
So if the Parent class could take an instance of itself in its constructor this would work (actually I'm dealing with multiple classes where some do and some do not). The hack-y thing I want to avoid is just passing the parent data structure as a property of another class:
class notChild():
def __init__ (self, dataInstance=None):
self.data = dataInstance
notChild.data.someparentmethod() # yuck.
I'm relatively new to OOP in python and I hope I'm overlooking something obvious. Thanks!
Ok. This is the solution I went with, which is specific to the implementation and I'd love to hear if there is a more general/pythonic way to do this:
class child(pandas.Panel4D):
def __init__ (self, d=None):
if isinstance(d, pandas.Panel4D):
d = d._data
super(child, self).__init__(d)
else:
super(child, self).__init__(d)
Essentially, if the child constructor is fed a parent instance, it accesses it's underlying data which is a class that the parent constructor can ingest.
I have an inherited class which i would like to point to from the base class. Example below
class Base
{
inherited* test;
};
class inherited: Base
{
};
the purpose of this is so that the base class (a character) contains a linked list of the inherited class (items)
ps apologies for any mistakes, i'm new to this site
It might be possible to trick the compiler into accomplishing this, but it's most certainly bad OOP design. If all you want to do is be able to store an instance of the inherited class but can treat it like the base class, then you can simply make inherited* test a base* test and it will accept pointers to either inherited or base (or any other subclass of base).
If you actually want base to treat that instance as inherited, you need to rethink your class hierarchy because you don't actually have an inheritance tree here.