⑴ 如何使用靜態方法,類方法或者抽象方法
方法是作為類的屬性(attribute)存儲的函數。你可以以下面的方式聲明和獲取函數:
>>> class Pizza(object):
... def __init__(self, size):
... self.size = size
... def get_size(self):
... return self.size
...
>>> Pizza.get_size
<unbound method Pizza.get_size>
Python告訴你的是,類Pizza的屬性get_size是一個非綁定的方法。這又指什麼呢?很快我們就會知道,試著調用一下:
>>> Pizza.get_size()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: unbound method get_size() must be called with Pizza instance as first argument (got nothing instead)
這里我們不能調用這個方法是因為它沒有被綁定到任一Pizza的實例上。一個方法需要一個實例作為它第一個參數(在Python 2中它必須是對應類的實例;在Python 3中可以是任何東西)。我們現在試試:
>>> Pizza.get_size(Pizza(42))
42
現在可以了!我們試用一個實例作為get_size方法的第一個參數調用了它,所以一切變得很美好。但是你很快會同意,這並不是一個很漂亮的調用方法的方式;因為每次我們想調用這個方法都必須使用到類。並且,如果我們不知道對象是哪個類的實例,這種方式就不方便了。
所以,Python為我們准備的是,它將類Pizza的所有的方法綁定到此類的任何實例上。這意味著類Pizza的任意實例的屬性get_size是一個已綁定的方法:第一個參數是實例本身的方法。
>>> Pizza(42).get_size
<bound method Pizza.get_size of <__main__.Pizza object at 0x10314b310>>
>>> Pizza(42).get_size()
42
如我們預期,現在不需要提供任何參數給get_size,因為它已經被綁定(bound),它的self參數是自動地設為Pizza類的實例。下面是一個更好的證明:
>>> m = Pizza(42).get_size
>>> m
<bound method Pizza.get_size of <__main__.Pizza object at 0x10314b350>>
>>> m()
42
因此,你甚至不要保存一個對Pizza對象的飲用。它的方法已經被綁定在對象上,所以這個方法已經足夠。
但是如何知道已綁定的方法被綁定在哪個對象上?技巧如下:
>>> m = Pizza(42).get_size
>>> m.__self__
<__main__.Pizza object at 0x10314b390>
>>> m == m.__self__.get_size
True
易見,我們仍然保存著一個對對象的引用,當需要知道時也可以找到。
在Python 3中,歸屬於一個類的函數不再被看成未綁定方法(unbound method),但是作為一個簡單的函數,如果要求可以綁定在對象上。所以,在Python 3中原理是一樣的,模型被簡化了。
>>> class Pizza(object):
... def __init__(self, size):
... self.size = size
... def get_size(self):
... return self.size
...
>>> Pizza.get_size
<function Pizza.get_size at 0x7f307f984dd0>
靜態方法
靜態方法是一類特殊的方法。有時,我們需要寫屬於一個類的方法,但是不需要用到對象本身。例如:
class Pizza(object):
@staticmethod
def mix_ingredients(x, y):
return x + y
def cook(self):
return self.mix_ingredients(self.cheese, self.vegetables)
這里,將方法mix_ingredients作為一個非靜態的方法也可以work,但是給它一個self的參數將沒有任何作用。這兒的decorator@staticmethod帶來一些特別的東西:
>>> Pizza().cook is Pizza().cook
False
>>> Pizza().mix_ingredients is Pizza().mix_ingredients
True
>>> Pizza().mix_ingredients is Pizza.mix_ingredients
True
>>> Pizza()
<__main__.Pizza object at 0x10314b410>
>>> Pizza()
<__main__.Pizza object at 0x10314b510>
>>>
Python不需要對每個實例化的Pizza對象實例化一個綁定的方法。綁定的方法同樣是對象,創建它們需要付出代價。這里的靜態方法避免了這樣的情況:
降低了閱讀代碼的難度:看到@staticmethod便知道這個方法不依賴與對象本身的狀態;
允許我們在子類中重載mix_ingredients方法。如果我們使用在模塊最頂層定義的函數mix_ingredients,一個繼承自Pizza的類若不重載cook,可能不可以改變混合成份(mix_ingredients)的方式。
類方法
什麼是類方法?類方法是綁定在類而非對象上的方法!
>>> class Pizza(object):
... radius = 42
... @classmethod
... def get_radius(cls):
... return cls.radius
...
>>> Pizza.get_radius
<bound method type.get_radius of <class '__main__.Pizza'>>
>>> Pizza().get_radius
<bound method type.get_radius of <class '__main__.Pizza'>>
>>> Pizza.get_radius is Pizza().get_radius
False
>>> Pizza.get_radius()
42
此處有問題。原文中
>>> Pizza.get_radius is Pizza().get_radius
True
還需要check一下。
不管你如何使用這個方法,它總會被綁定在其歸屬的類上,同時它第一個參數是類本身(記住:類同樣是對象)
何時使用這種方法?類方法一般用於下面兩種:
1. 工廠方法,被用來創建一個類的實例,完成一些預處理工作。如果我們使用一個@staticmethod靜態方法,我們可能需要在函數中硬編碼Pizza類的名稱,使得任何繼承自Pizza類的類不能使用我們的工廠用作自己的目的。
class Pizza(object):
def __init__(self, ingredients):
self.ingredients = ingredients
@classmethod
def from_fridge(cls, fridge):
return cls(fridge.get_cheese() + fridge.get_vegetables())
靜態方法調靜態方法:如果你將一個靜態方法分解為幾個靜態方法,你不需要硬編碼類名但可以使用類方法。使用這種方式來聲明我們的方法,Pizza這個名字不需要直接被引用,並且繼承和方法重載將會完美運作。
class Pizza(object):
def __init__(self, radius, height):
self.radius = radius
self.height = height
@staticmethod
def compute_circumference(radius):
return math.pi * (radius ** 2)
@classmethod
def compute_volume(cls, height, radius):
return height * cls.compute_circumference(radius)
def get_volume(self):
return self.compute_volume(self.height, self.radius)
抽象方法
抽象方法在一個基類中定義,但是可能不會有任何的實現。在Java中,這被描述為一個介面的方法。
所以Python中最簡單的抽象方法是:
class Pizza(object):
def get_radius(self):
raise NotImplementedError
任何繼承自Pizza的類將實現和重載get_radius方法,否則會出現異常。這種獨特的實現抽象方法的方式也有其缺點。如果你寫一個繼承自Pizza的類,忘記實現get_radius,錯誤將會在你使用這個方法的時候才會出現。
>>> Pizza()
<__main__.Pizza object at 0x106f381d0>
>>> Pizza().get_radius()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
File "<stdin>", line 3, in get_radius
NotImplementedError
有種提前引起錯誤發生的方法,那就是當對象被實例化時,使用Python提供的abc模塊。
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def get_radius(self):
"""Method that should do something."""
使用abc和它的特類,一旦你試著實例化BasePizza或者其他繼承自它的類,就會得到TypeError
>>> BasePizza()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: Can't instantiate abstract class BasePizza with abstract methods get_radius
混合靜態方法、類方法和抽象方法
當我們構建類和繼承關系時,終將會碰到要混合這些方法decorator的情況。下面提幾個tip。
記住聲明一個類為抽象類時,不要冷凍那個方法的prototype。這是指這個方法必須被實現,不過是可以使用任何參數列表來實現。
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def get_ingredients(self):
"""Returns the ingredient list."""
class Calzone(BasePizza):
def get_ingredients(self, with_egg=False):
egg = Egg() if with_egg else None
return self.ingredients + egg
這個是合法的,因為Calzone完成了為BasePizza類對象定義的介面需求。就是說,我們可以把它當作一個類方法或者靜態方法來實現,例如:
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def get_ingredients(self):
"""Returns the ingredient list."""
class DietPizza(BasePizza):
@staticmethod
def get_ingredients():
return None
這樣做同樣爭取,並且完成了與BasePizza抽象類達成一致的需求。get_ingredients方法不需要知道對象,這是實現的細節,而非完成需求的評價指標。
因此,你不能強迫抽象方法的實現是正常的方法、類方法或者靜態方法,並且可以這樣說,你不能。從Python 3開始(這就不會像在Python 2中那樣work了,見issue5867),現在可以在@abstractmethod之上使用@staticmethod和@classmethod了。
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
ingredient = ['cheese']
@classmethod
@abc.abstractmethod
def get_ingredients(cls):
"""Returns the ingredient list."""
return cls.ingredients
不要誤解:如果你認為這是強迫你的子類將get_ingredients實現為一個類方法,那就錯了。這個是表示你實現的get_ingredients在BasePizza類中是類方法而已。
在一個抽象方法的實現?是的!在Python中,對比與Java介面,你可以在抽象方法中寫代碼,並且使用super()調用:
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
default_ingredients = ['cheese']
@classmethod
@abc.abstractmethod
def get_ingredients(cls):
"""Returns the ingredient list."""
return cls.default_ingredients
class DietPizza(BasePizza):
def get_ingredients(self):
return ['egg'] + super(DietPizza, self).get_ingredients()
文/Not_GOD(簡書作者)
原文鏈接:http://www.jianshu.com/p/880d6a3ffdde
著作權歸作者所有,轉載請聯系作者獲得授權,並標注「簡書作者」。
⑵ JAVA中,什麼是抽象類抽象類中是否一定包還抽象方法~
java中用abstract聲明的類就叫做抽象類,抽象類中抽象方法可有可無,但通常都含有抽象方法(這是定義抽象類的目的所在)讓子類繼承,如果子類沒有把抽象類中所有的抽象方法都重寫,則這個繼承了抽象類的子類也會成為抽象類;如果子類把抽象類中所有的抽象方法都重寫,則這個子類就可以實例化了。
⑶ java抽象類能不能加註解方式
抽象類是用來捕捉子類的通用特性的,是被用來創建繼承層級里子類的模板。現實中有些父類中的方法確實沒有必要寫,因為各個子類中的這個方法肯定會有不同;而寫成抽象類,這樣看代碼
php中什麼是抽象方法和抽象類2020-07-29
抽象方法是指在類中定義的沒有方法體的方法。如果一個類中有一個方法是抽象方法,那麼這個類就是抽象類,抽象類中可以包含非抽象方法。在聲明抽象方法和抽象類時,需要使用abstra
抽象類和介面有什麼異同點2020-08-13
抽象類和介面的區別:(推薦教程:java入門教程)抽象類中既可以包含抽象方法,也可以包含非抽象的普通方法;而介面中的方法必須是抽象方法。抽象類中的抽象方法的訪問類型可以是public
php中抽象類和介面有哪些不同點2020-11-05
php中抽象類和介面的不同點有:1、抽象類可以有屬性和普通方法,介面不能有屬性和普通方法;2、抽象類中不一定有抽象方法,介面中一定有抽象方法;3、抽象類的抽象方法必須用abstract
抽象類與介面有什麼聯系2020-08-03
聯系:(推薦教程:java入門教程)1、都可以擁有抽象方法2、都不可以直接創建對象3、都依靠於子類存在才有意義,子類必須實現其所有的抽象方法4、都可以實現多態區別:成員不同:介面中沒
php抽象類和介面之間有什麼區別?2020-07-16
本篇文章給大家介紹一下php抽象類和介面的區別。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有所幫助。抽象類官方描述請查看文檔,下面是官方描述的梳理版本:定義為
詳解PHP中abstract(抽象)、final(最終)和static(靜態)原理與用法2020-07-14
本文實例講述了PHP中abstract(抽象)、final(最終)和static(靜態)原理與用法。分享給大家供大家參考,具體如下:abstract(抽象)PHP 5 支持抽象類和抽象方法。定義為抽象的類不能
什麼是java註解2020-08-05
註解和反射是Java中非常讓人容易忽略的東西,但卻很重要,在主流的Spring中更是充滿了註解,註解和注釋很像,兩者其實本質就差不多,注釋是給我們程序員看的,而註解呢其實就是給程序看
常見的Java註解有哪些2020-07-21
註解(Annotation)(推薦教程:java入門教程)從 JDK 5.0 開始, Java 增加了對元數據(MetaData) 的支持, 也就是Annotation(註解)Annotation 其實就是代碼里的特殊標記, 這些標記可
C# 中虛方法和抽象方法2020-07-23
今天在雲和學院學了很多,我這次只能先總結一下C#中的虛方法和抽象的運用。理論:虛方法:用virtual修飾的方法叫做虛方法虛方法可以在子類中通過override關鍵字來重寫常見的虛方
java代碼編譯順序是什麼2020-10-27
java代碼編譯順序:首先源代碼進入詞法分析器,token流後進入語法分析器;然後進行抽象語法樹後進行語義分析器;接著註解抽象語法樹,並使用位元組碼生成器;最後生成jvm位元組碼。java代碼
抽象數據類型有哪些2020-07-02
抽象數據類型是一種對「數據結構」的描述,這種描述是「抽象」的,描述內容有:1、數據對象集;2、與數據集合相關聯的操作集。抽象數據類型抽象數據類型(Abstract Data Type)是一種
工廠模式和抽象工廠模式的區別?2020-07-28
工廠模式和抽象工廠模式的區別?1、工廠模式在使用時可以隨時設置變數,不用提前進行設置,抽象工廠模式則需要每次增加產品時,進行修改類方法;2、工廠模式可以使用兩個介面以及三個
實例介紹java中的Calendar類2020-07-23
日歷類,它是一個抽象類,封裝了所有的日歷欄位值,通過統一的方法根據傳入不同的日歷欄位可以獲取值。(推薦教程:java入門教程)1、得到一個日歷對象Calendar c = Calendar.getInstan
java和php介面的區別是什麼2020-09-01
java和php介面的區別是:1、php中在介面中的抽象方法只能是public的,默認也是public許可權;2、java中私有方法使用private修飾,供介面中的默認方法或者靜態方法調用。【相關學習推
⑷ java抽象方法
new一個實例再指向原先的抽象類,這個在JAVA當中叫做多態性。當一個子類的實例指向父抽象類的時候,那麼父抽象類所定義的一個沒有被實例化的對象就可以使用父抽象類當中所有的被子類實現的抽象方法,但是不可以使用子類新加入的方法。不知道你清楚了沒有!
⑸ 如何在類中聲明抽象方法並使他返回一個字元串
用abstract修飾,同時將返回值設置為string類型即可。
抽象類,抽象方法都可用abstract修飾,來表示其抽象的意思。返回值是字元串,字元串用string表示,所以講返回值的類型設置為string就行。
⑹ C# 子類實現父類抽象方法 如何顯示父類注釋
繼承是實現代碼的重用而不是注釋的重用,程序運行時,會把注釋當成廢話給過濾掉
⑺ php中如何給類規范的注釋
需要准備的材料分別是:電腦、phpstrom編輯器。
1、首先,打開phpstrom編輯器,新建php文件,例如:index.php,定義一個函數示例。
⑻ java里的抽象方法是怎麼定義的
1 用abstract關鍵字來修飾一個類時,這個類叫做抽象類;用abstract來修飾一個方法時,該方法叫做抽象方法。例如 :
abstract class Animal { //用abstract來定義一個Animal為抽象類
}
public abstract void enjoy(); //用abstract來定義一個抽象方法"enjoy"
⑼ 什麼是抽象類和抽象方法
抽象類就是不能使用new方法進行實例化的類,即沒有具體實例對象的類。抽象類有點類似「模板」的作用,目的是根據其格式來創建和修改新的類。對象不能由抽象類直接創建,只可以通過抽象類派生出新的子類,再由其子類來創建對象。當一個類被聲明為抽象類時,要在這個類前面加上修飾符abstract。 在抽象類中的成員方法可以包括一般方法和抽象方法。抽象方法就是以abstract修飾的方法,這種方法只聲明返回的數據類型、方法名稱和所需的參數,沒有方法體,也就是說抽象方法只需要聲明而不需要實現。當一個方法為抽象方法時,意味著這個方法必須被子類的方法所重寫,否則其子類的該方法仍然是abstract的,而這個子類也必須是抽象的,即聲明為abstract。 抽象類中不一定包含抽象方法,但是包含抽象方法的類一定要被聲明為抽象類。抽象類本身不具備實際的功能,只能用於派生其子類。抽象類中可以包含構造方法,但是構造方法不能被聲明為抽象。 抽象類不能用final來修飾,即一個類不能既是最終類又是抽象類。 abstract不能與private、static、final、native並列修飾同一個方法。 程序舉例:abstract class Animal //定義抽象類 abstract void eat(); //定義抽象方法}class Horse extends Animal //定義繼承Animal的子類 void eat() //重寫父類的抽象方法 }class Dog extends Animal void eat() }class test}運行結果: 馬吃草料! 狗吃骨頭!
⑽ java,實現抽象方法的方法
答案是肯定的。我看你是不太理解抽象方法。我來是說一下我的理解吧。也不知道對不對。你掂量掂量吧。呵呵。抽象方法是這樣的。
抽象方法就是把子類要一定要實現的方法抽象出來。放到父類。繼承父類的子類就一定得重寫父類中的抽象方法。而非抽象方法不一定要重寫。父類的抽象方法不是一定要繼承。而是一定要重寫。重寫就覆蓋了父類的相應的方法(實際是隱藏,說覆蓋形象點).子類可以使用父類的非私有方法和非私有變數。