vidit02100
vidit02100

Reputation: 153

Instance error in OOP design: Instance of Card has No points member

I'm reading this book called Master Object Oriented programming Python by Steven Lott.

I came across this code:

class Card:
    def  __init__( self, rank, suit ):
        self.suit= suit
        self.rank= rank
        self.hard, self.soft = self._points()
class NumberCard( Card ):
    def _points( self ):
        return int(self.rank), int(self.rank)
class AceCard( Card ):
    def _points( self ):
        return 1, 11
class FaceCard( Card ):
    def _points( self ):
        return 10, 10

I'm not able to understand how can self._points() in Card be legal expression.

I run the code in compiler too it stats the following error Instance of Card has No points member

Error Image Full Code I have kept it as gist here

Upvotes: 2

Views: 74

Answers (2)

atline
atline

Reputation: 31584

From your error: it is just a pylint issue, if you do not do something like c = Card(1, 2), it will be ok.

The code in fact is correct.

It intends you will call it like n = NumberCard(1, 2), then __init__ will be used by its subclass, and subclass has the function _points.

In fact, for other language, usually we need to define a _points function in parent class. Then, subclass could override the function in parent class. But python is not so strict, so you could do without define _points function in parent class, but then you will just able to new a object for its subclass not parent class.

To sum all, what you need to google is function override of OOP.

Upvotes: 1

blhsing
blhsing

Reputation: 106598

The __init__() function of the base class, Card, tries to access the member function _points(), when it has none. That its subclasses all have such a member function doesn't help the base class from getting this member function. You simply can't instantiate Card directly because it really is an abstract class.

You should use the abc module to declare Card as an abstract class, and Card._points as an abstract method, and instantiate child classes instead:

from abc import ABC, abstractmethod

class Card(ABC):
    def  __init__( self, rank, suit ):
        self.suit= suit
        self.rank= rank
        self.hard, self.soft = self._points()
    @abstractmethod
    def _points(self):
        return None, None
class NumberCard( Card ):
    def _points( self ):
        return int(self.rank), int(self.rank)
class AceCard( Card ):
    def _points( self ):
        return 1, 11
class FaceCard( Card ):
    def _points( self ):
        return 10, 10

a=AceCard(1,2)
print(a.hard, a.soft)

Upvotes: 1

Related Questions